package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.handle.explain.impl.CustomerExplainHandleImpl;
import com.xbongbong.formula.constant.Constant;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.BusinessRuleUserPermissionHelp;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.FieldAttrConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasCommentEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaymentSheetTypeEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.help.BusinessUserTeamHelp;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataValidateDataHelp;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.SaasStageHelp;
import com.xbongbong.paas.help.StageLogHelp;
import com.xbongbong.paas.help.TransactionHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasCommentModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.pojo.AttrValuePojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.CustomerCommunicateDeleteDTO;
import com.xbongbong.paas.pojo.dto.CustomerMergeDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddGetDTO;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.FormDataRepeatDTO;
import com.xbongbong.paas.pojo.dto.FormDataThoroughDeleteDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataAddGetVO;
import com.xbongbong.paas.pojo.vo.FormDataRepeatVO;
import com.xbongbong.paas.pojo.vo.LinkResultDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.service.CallCenterCommonService;
import com.xbongbong.paas.service.CustomerRuleService;
import com.xbongbong.paas.service.DepartmentService;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.PaasFormExplainService;
import com.xbongbong.paas.service.PaasFormService;
import com.xbongbong.paas.service.TransferBackRuleScriptService;
import com.xbongbong.paas.service.dynamic.crm.strategy.CustomerDynamicStrategy;
import com.xbongbong.paas.service.dynamic.crm.strategy.DynamicStrategyFactory;
import com.xbongbong.paas.service.dynamic.help.DynamicDetailsHelper;
import com.xbongbong.paas.service.log.crm.help.OperationLogHelp;
import com.xbongbong.paas.service.log.crm.operation.CustomerOperationLogHandle;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.GaodeGeoHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.ItemUtil;
import com.xbongbong.parent.factory.TeamDataFactory;
import com.xbongbong.parent.interfaces.DynamicStrategy;
import com.xbongbong.parent.interfaces.TeamStrategy;
import com.xbongbong.parent.interfaces.logger.OperationLogFactory;
import com.xbongbong.parent.interfaces.logger.OperationLogHandle;
import com.xbongbong.parent.parse.data.BaseFormDataLinkDataHelp;
import com.xbongbong.parent.parse.data.FormDataListAnalysisDataHelp;
import com.xbongbong.parent.parse.data.LinkDataHelp;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.businessdata.pojo.dto.FocusDTO;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.businessrule.pojo.dto.OperationDTO;
import com.xbongbong.pro.common.pojo.AddressPojo;
import com.xbongbong.pro.common.pojo.dto.CustomerCheckRepeatDTO;
import com.xbongbong.pro.common.pojo.dto.RepeatCommonConditionDTO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.contact.pojo.dto.ContactDeleteBatchDTO;
import com.xbongbong.pro.contact.pojo.dto.ContactUpdateBatchDTO;
import com.xbongbong.pro.contact.pojo.dto.ContactUpdateDTO;
import com.xbongbong.pro.contactuser.pojo.dto.ContactUserDeleteBatchDTO;
import com.xbongbong.pro.contract.pojo.dto.QuotationUpdateBatchDTO;
import com.xbongbong.pro.contract.pojo.dto.QuotationUpdateDTO;
import com.xbongbong.pro.customer.pojo.dto.ChangeStatusDTO;
import com.xbongbong.pro.customer.pojo.dto.CustomerCardDTO;
import com.xbongbong.pro.customer.pojo.dto.CustomerDeleteBatchDTO;
import com.xbongbong.pro.customer.pojo.dto.CustomerEditAttrUpdateDTO;
import com.xbongbong.pro.customer.pojo.dto.CustomerUpdateBatchDTO;
import com.xbongbong.pro.customer.pojo.dto.CustomerUpdateDTO;
import com.xbongbong.pro.customer.pojo.vo.CustomerDeleteBatchVO;
import com.xbongbong.pro.customer.pojo.vo.CustomerEditAttrUpdateVO;
import com.xbongbong.pro.customer.pojo.vo.CustomerUpdateBatchVO;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerCommunicateDeleteBatchDTO;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerCommunicateUpdateBatchDTO;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerCommunicateUpdateDTO;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerDynamicAddDTO;
import com.xbongbong.pro.customercommunicate.pojo.dto.DynamicDTO;
import com.xbongbong.pro.customeruser.pojo.dto.CustomerUserDeleteBatchDTO;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.SpecialUpdateCustomerDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataValueEntity;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicDeleteDTO;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicMergeDTO;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicSaveDTO;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ContactErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemLabelErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.UserTeamErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.export.pojo.ExportLinkDataPojo;
import com.xbongbong.pro.formdata.pojo.AfterSavePojo;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.dto.LinkFormItemDTO;
import com.xbongbong.pro.formexplain.pojo.vo.LinkFormItemVO;
import com.xbongbong.pro.invoice.pojo.dto.InvoiceDeleteBatchDTO;
import com.xbongbong.pro.listbatch.pojo.TeamBatchPojo;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.listbatch.pojo.dto.ListBatchDTO;
import com.xbongbong.pro.log.pojo.dto.CustomerMergeLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteBatchOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.log.pojo.dto.UpdateBatchOperationLogDTO;
import com.xbongbong.pro.message.constant.CustomerPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.ConsistencySyncRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.PublicGroupRabbitMqDTO;
import com.xbongbong.pro.opportunity.pojo.JudgeStageChangedPojo;
import com.xbongbong.pro.opportunity.pojo.StageLogSavePojo;
import com.xbongbong.pro.opportunity.pojo.dto.OpportunityDeleteBatchDTO;
import com.xbongbong.pro.opportunity.pojo.dto.OpportunityUpdateBatchDTO;
import com.xbongbong.pro.opportunity.pojo.dto.OpportunityUpdateDTO;
import com.xbongbong.pro.permission.pojo.dto.VerifyUpdatePermissionDTO;
import com.xbongbong.pro.publicgroupcustomer.pojo.dto.CustomerChangeGroupDTO;
import com.xbongbong.pro.pushnotify.dto.PushNotifyDeleteDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.rabbitmq.producer.PublicGroupProducer;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.pro.team.TeamAfterVerifyDTO;
import com.xbongbong.pro.team.TeamVerifyDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.pro.workorder.pojo.dto.QuotationDeleteBatchDTO;
import com.xbongbong.saas.analytical.impl.CustomerValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.CabinetFileEntity;
import com.xbongbong.saas.domain.entity.CustomerFocusEntity;
import com.xbongbong.saas.domain.entity.CustomerStageEntity;
import com.xbongbong.saas.domain.entity.CustomerStageLogEntity;
import com.xbongbong.saas.domain.entity.LikeEntity;
import com.xbongbong.saas.domain.entity.PaymentBalanceEntity;
import com.xbongbong.saas.domain.entity.StaticMarketForCustomerMergeEntity;
import com.xbongbong.saas.domain.entity.TagLinkEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerCommunicateEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.domain.entity.ext.QuotationEntityExt;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.CheckRepeatRuleEnum;
import com.xbongbong.saas.enums.ClueRuleSettingEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.LinkAddOperationFlagEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.PhoneExtEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.InvoiceEnum;
import com.xbongbong.saas.enums.business.PaymentBalanceEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.dictionary.ClueStatusEnum;
import com.xbongbong.saas.enums.dictionary.DictionaryEnum;
import com.xbongbong.saas.enums.dictionary.PublicEnum;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.MarketManagementBusinessHelp;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasDetailPermissionHelp;
import com.xbongbong.saas.help.SaasGetHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.ScoreCalculateHelp;
import com.xbongbong.saas.help.workflow.CustomerStageLogHelp;
import com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp;
import com.xbongbong.saas.model.CabinetFileModel;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.CustomerCommunicateModel;
import com.xbongbong.saas.model.CustomerFocusModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerStageLogModel;
import com.xbongbong.saas.model.CustomerStageModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.DataDictionaryModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.model.LikeModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.TagLinkModel;
import com.xbongbong.saas.service.CommonService;
import com.xbongbong.saas.service.ConsistencySyncService;
import com.xbongbong.saas.service.ContactService;
import com.xbongbong.saas.service.ContactUserService;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.service.CustomerService;
import com.xbongbong.saas.service.CustomerUserService;
import com.xbongbong.saas.service.DictionaryService;
import com.xbongbong.saas.service.InvoiceService;
import com.xbongbong.saas.service.ListBatchService;
import com.xbongbong.saas.service.OpportunityService;
import com.xbongbong.saas.service.PaymentBalanceService;
import com.xbongbong.saas.service.PaymentSheetService;
import com.xbongbong.saas.service.PersonLabelService;
import com.xbongbong.saas.service.PushNotifyService;
import com.xbongbong.saas.service.QuotationService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.service.ScoreRuleService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author haibing.zhang
 * @version v1.0
 * @date 2019/1/18
 * @since v1.0
 */
@Service("customerService")
public class CustomerServiceImpl implements CustomerService {

    private static final Logger LOG = LoggerFactory.getLogger(CustomerServiceImpl.class);

    @Resource
    private CustomerModel customerModel;
    @Resource
    private CustomerFocusModel customerFocusModel;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private ContactService contactService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private UserModel userModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private InvoiceService invoiceService;
    @Resource
    private OpportunityService opportunityService;
    @Resource
    private ContactUserService contactUserService;
    @Resource
    @Lazy
    private CustomerCommunicateService customerCommunicateService;
    @Resource
    private CustomerUserService customerUserService;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private DataDictionaryModel dataDictionaryModel;
    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private CallCenterCommonService callCenterCommonService;
    @Resource
    private SaasGetHelp saasGetHelp;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasFormService paasFormService;
    @Resource
    private TagLinkModel tagLinkModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PaasFormExplainService paasFormExplainService;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private DictionaryService dictionaryService;
    @Resource
    private CommonService commonService;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private PushNotifyService pushNotifyService;
    @Resource
    private CustomerStageModel customerStageModel;
    @Resource
    private CustomerStageLogModel customerStageLogModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private CustomerRuleService customerRuleService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private FormDataValidateDataHelp formDataValidateDataHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private UserHelp userHelp;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private ListBatchService listBatchService;
    @Resource
    private DepartmentService departmentService;
    @Resource
    private QuotationService quotationService;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private SaasDetailPermissionHelp saasDetailPermissionHelp;
    @Resource
    private BusinessRuleUserPermissionHelp businessRuleUserPermissionHelp;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private PaymentBalanceService paymentBalanceService;
    @Resource
    private PaymentSheetService paymentSheetService;
    @Resource
    private CabinetFileModel cabinetFileModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private PaasFormHelp paasFormHelp;
    @Resource
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private CustomerCommunicateModel customerCommunicateModel;
    @Resource
    private MarketManagementBusinessHelp marketManagementBusinessHelp;
    @Resource
    private ScoreRuleService scoreRuleService;
    @Resource
    private ScoreCalculateHelp scoreCalculateHelp;
    @Resource
    private ConsistencySyncService consistencySyncService;
    @Resource
    private PaasCommentModel paasCommentModel;
    @Resource
    private LikeModel likeModel;
    @Resource
    private LabelModel labelModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private CustomerStageLogHelp customerStageLogHelp;
    @Resource
    private CustomerValidateAnalyticalServiceImpl customerAnalyticalService;
    @Resource
    private PersonLabelService personLabelService;
    @Resource
    private CustomerExplainHandleImpl customerExplainHandle;
    @Resource
    private StageLogHelp stageLogHelp;
    @Resource
    private SaasStageHelp saasStageHelp;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private OperationLogFactory operationLogFactory;
    @Resource
    private CustomerOperationLogHandle customerOperationLogHandle;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private TeamDataHelp teamDataHelp;
    @Resource
    private TeamDataFactory teamDataFactory;
    @Resource
    private BusinessUserTeamHelp businessUserTeamHelp;
    @Resource
    private PublicGroupProducer publicGroupProducer;
    @Resource
    private TransferBackRuleScriptService transferBackRuleScriptService;
    @Resource
    private MarketActivityForStaticHelp marketActivityForStaticHelp;
    @Resource
    private DynamicStrategyFactory dynamicStrategyFactory;
    @Resource
    private DynamicDetailsHelper dynamicDetailsHelper;
    @Resource
    private OperationLogHelp operationLogHelp;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private TransactionHelp transactionHelp;
    @Resource
    private BaseFormDataLinkDataHelp baseFormDataLinkDataHelp;
    @Resource
    private LinkDataHelp linkDataHelp;


    /**
     * 客户保存前校验
     *
     * @param validateDataDTO 业务数据
     * @throws XbbException 抛出业务异常
     * @author haibin.zhang
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        customerAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 客户保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 抛出业务异常
     * @author haibin.zhang
     */
    @Override
    public AfterSavePojo afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        AfterSavePojo afterSavePojo = new AfterSavePojo();
        String corpid = saasFormSaveDTO.getCorpid();
        Integer businessType = saasFormSaveDTO.getBusinessType();
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONObject oldData = saasFormSaveDTO.getOldData();
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = newPaasFormDataEntity.getId();
        Boolean isNew = saasFormSaveDTO.getIsNew();
        Long formId = newPaasFormDataEntity.getFormId();
        String customerName = FastJsonHelper.getStringOrDefaultFromFormData(newData, CustomerManagementEnum.NAME.getAttr(), "");
        String stageCode = FastJsonHelper.getStringOrDefaultFromFormData(newData, CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), "");
        String oldStageCode = FastJsonHelper.getStringOrDefaultFromFormData(oldData, CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), "");
        Integer reasonId = FastJsonHelper.getIntegerOrDefaultFromFormData(newData, CustomerManagementEnum.WASTAGE.getAttr(), BasicConstant.ZERO);
        Integer oldReasonId = FastJsonHelper.getIntegerOrDefaultFromFormData(oldData, CustomerManagementEnum.WASTAGE.getAttr(), BasicConstant.ZERO);
        String wastageMemo = FastJsonHelper.getStringOrDefaultFromFormData(newData, CustomerManagementEnum.WASTAGE_MEMO.getAttr(), "");
        if (Objects.isNull(saasFormSaveDTO.getOwnerId()) || (Objects.nonNull(saasFormSaveDTO.getOwnerId()) && saasFormSaveDTO.getOwnerId().isEmpty())) {
            saasFormSaveDTO.setSubBusinessType(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode());
        }

        // 新建的时候阶段不为空或者编辑时阶段不一致才需要更改阶段
        JudgeStageChangedPojo judgeStageChangedPojo = stageLogHelp.judgeStageChanged(corpid, formId, dataId, stageCode, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        if (judgeStageChangedPojo.getIsStageChanged()) {
            try {
                saasStageHelp.stageJump(saasFormSaveDTO, CustomerManagementEnum.CUSTOMER_STAGE.getAttr());
            } catch (Exception e) {
                // 感觉这段不能走异步
                LOG.error("客户阶段变更异常", e);
            }
        }
        // 异步的放下面

        if (Objects.equals(saasFormSaveDTO.getSubBusinessType(), XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode()))  {
            if (!isNew && !Objects.equals(oldData.getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr()), 1)) {
                ListBatchDTO listBatchDTO = new ListBatchDTO();
                BeanUtil.copyProperties(saasFormSaveDTO, listBatchDTO);
                listBatchDTO.setDataIdList(Collections.singletonList(dataId));
                listBatchDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                listBatchDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                listBatchDTO.setFormId(newPaasFormDataEntity.getFormId());
                // 新建编辑场景没有团队需要退回公海池，防止当前操作人没有退回公海池权限导致下面的方法执行成功，补充权限
                listBatchDTO.getLoginUser().getPermSet().add(ProPermissionAliasEnum.CUSTOMER_BACK.getAlias());
                listBatchService.backCustomer(listBatchDTO);
            } else {
                SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo();
                afterSavePojo = teamDataHelp.saveUserTeam(saasNeedRedundantAttrPoJo, dataId, newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), false);
            }
        } else {
            SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo();
            //加个返回值主要是老哥说业务规则那边需要返回，后面有问题找老哥
            afterSavePojo = teamDataHelp.saveUserTeam(saasNeedRedundantAttrPoJo, dataId, newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), false);

            // 因为公海池规则报错导致当前数据没有团队添加成功，需要把数据退回公海池
            if (!afterSavePojo.getHaveTeam()) {
                ListBatchDTO listBatchDTO = new ListBatchDTO();
                BeanUtil.copyProperties(saasFormSaveDTO, listBatchDTO);
                listBatchDTO.setDataIdList(Collections.singletonList(dataId));
                listBatchDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                listBatchDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                listBatchDTO.setFormId(newPaasFormDataEntity.getFormId());
                // 新建编辑场景没有团队需要退回公海池，防止当前操作人没有退回公海池权限导致下面的方法执行成功，补充权限
                listBatchDTO.getLoginUser().getPermSet().add(ProPermissionAliasEnum.CUSTOMER_BACK.getAlias());
                listBatchService.backCustomer(listBatchDTO);
            }
        }

        Runnable runnable = () -> {
            String creatorId = newPaasFormDataEntity.getCreatorId();
            UserEntity creatorUser = userModel.getByKey(creatorId, corpid);
            String creatorUserName = Objects.isNull(creatorUser) ? "" : creatorUser.getName();
            if (isNew) {
                try {
                    if (Objects.equals(saasFormSaveDTO.getSubBusinessType(), XbbRefTypeEnum.CUSTOMER_FOCUS.getCode())) {
                        FocusDTO focusDTO = new FocusDTO();
                        focusDTO.setBusinessType(saasFormSaveDTO.getBusinessType());
                        focusDTO.setCorpid(saasFormSaveDTO.getCorpid());
                        focusDTO.setUserId(newPaasFormDataEntity.getCreatorId());
                        focusDTO.setDataIdList(Collections.singletonList(dataId));
                        focusDTO.setFocus(1);
                        focusDTO.setFromNew(BasicConstant.ONE);
                        focus(focusDTO);
                    }
                } catch (Exception e) {
                    LOG.error("新建重点客户关注", e);
                }

                // 客户创建项目日志
                try {
                    if(Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),saasFormSaveDTO.getDistributorMark())) {
                        String isPublic = newData.getString(CustomerManagementEnum.IS_PUBLIC.getAttr());
                        String publicName = Objects.equals(isPublic, "1") ? PublicEnum.PUBLIC.getName() : XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getName();
                        String operate = Objects.equals(saasFormSaveDTO.getIsImport(), 1) ? I18nMessageUtil.getMessage(I18nStringConstant.IMPORTED) : I18nMessageUtil.getMessage(I18nStringConstant.ADD);
                        String communicateMemo = creatorUserName + operate + publicName + ":" + customerName;
                        CustomerDynamicAddDTO customerDynamicAddDTO = CustomerDynamicAddDTO.initCustomerDynamicAddDTO(corpid, creatorId, null, communicateMemo, dataId, customerName, 0L, null, "", ProjectLogEnum.CUSTOMER_CREATE.getSubType());
                        customerDynamicAddDTO.setDistributorMark(DistributorMarkEnum.DISTRIBUTOR.getCode());
                        customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
                    }else {
                        DynamicStrategy dynamicStrategy = dynamicStrategyFactory.getDynamicStrategy(ProjectLogEnum.CUSTOMER_CREATE.getSubType());
                        transactionHelp.afterCommitOrCommitNow(p -> {
                            dynamicStrategy.save(DynamicSaveDTO.initDynamicSaveDTO(dataId, formId, saasFormSaveDTO, creatorUser, judgeStageChangedPojo));
                        });
                    }
                } catch (Exception e) {
                    LOG.error("客户创建项目日志", e);
                }

                try {
                    if (!Objects.equals(saasFormSaveDTO.getIsImport(), 1)) {
                        // 客户创建消息推送
                        CustomerEntityExt customerEntityExt = new CustomerEntityExt();
                        BeanUtil.copyProperties(newPaasFormDataEntity, customerEntityExt);
                        List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(saasFormSaveDTO.getCorpid(), PushTypeEnum.CUSTOMER_ADD_PUSH.getCode(), PushTypeEnum.CUSTOMER_ADD_PUSH.getSubCode(), creatorUser, customerEntityExt);
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), saasFormSaveDTO.getBusinessType(), saasFormSaveDTO.getSubBusinessType());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(saasFormSaveDTO.getCorpid(), pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_ADD_TITLE), String.format(I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_ADD_CONTENT), creatorUser.getName(), customerName), null, options);
                        baseProducer.sendMessage(PushTypeEnum.CUSTOMER_ADD_PUSH, messageRabbitMqDTO);
                    }
                } catch (Exception e) {
                    LOG.error("客户创建消息推送", e);
                }

                try {
                    //根据分组规则绑定所属分组
                    boolean publicPoolSeniorModel = commonHelp.isCustomerPublicPoolSeniorModel(corpid);
                    if (publicPoolSeniorModel && !Objects.equals(saasFormSaveDTO.getIsImport(), 1)) {
                        PublicGroupRabbitMqDTO mqDTO = new PublicGroupRabbitMqDTO(corpid, Collections.singletonList(dataId), newPaasFormDataEntity.getFormId(), businessType);
                        publicGroupProducer.bindPublicGroup(mqDTO);
                    }
                } catch (Exception e) {
                    LOG.error("绑定公海分组失败", e);
                }

            } else {
                try {
                    if (!Objects.equals(oldData.getString(CustomerManagementEnum.TYPE.getAttr()), newData.getString(CustomerManagementEnum.TYPE.getAttr()))) {
                        Long customerId = saasFormSaveDTO.getNewPaasFormDataEntity().getId();
                        //是否开启公海高级模式
                        boolean customerSeniorModel = commonHelp.isCustomerPublicPoolSeniorModel(corpid);
                        // 去除客户标签
                        if (customerSeniorModel){
                            transferBackRuleScriptService.deletePublicSeniorTag(corpid,Collections.singletonList(customerId),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),formId);
                        }else {
                            customerRuleService.deletePublicTag(corpid, Collections.singletonList(customerId));
                        }
                        String type = dataDictionaryModel.getDictionaryValue(saasFormSaveDTO.getCorpid(), DictionaryEnum.CUSTOMER_STATUS, newData.getInteger(CustomerManagementEnum.TYPE.getAttr()));
                        // 客户状态变更消息推送
                        CustomerEntityExt customerEntityExt = new CustomerEntityExt();
                        UserVO userVO = saasFormSaveDTO.getLoginUser();
                        UserEntity userEntity = new UserEntity();
                        if (Objects.equals(saasFormSaveDTO.getIsFromProcess(), 1)) {
                            userEntity = userModel.getByKey(saasFormSaveDTO.getProcessCreatorId(), corpid, null);
                        } else {
                            BeanUtil.copyProperties(userVO, userEntity);
                            userEntity.setUserId(userVO.getUserId());
                            userEntity.setName(userVO.getName());
                            userEntity.setCorpid(corpid);
                        }
                        BeanUtil.copyProperties(newPaasFormDataEntity, customerEntityExt);
                        List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(saasFormSaveDTO.getCorpid(), PushTypeEnum.CUSTOMER_CHANGE_PUSH.getCode(), PushTypeEnum.CUSTOMER_CHANGE_PUSH.getSubCode(), userEntity, customerEntityExt);
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), saasFormSaveDTO.getBusinessType(), saasFormSaveDTO.getSubBusinessType());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(saasFormSaveDTO.getCorpid(), pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STATUS_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STATUS_CHANGE_CONTENT), userEntity.getName(), customerName, type), null, options);
                        baseProducer.sendMessage(PushTypeEnum.CUSTOMER_CHANGE_PUSH, messageRabbitMqDTO);
                    }
                } catch (Exception e) {
                    LOG.error("客户状态变更消息推送", e);
                }
            }

            try {
                Integer isBringCustomer = saasFormSaveDTO.getIsBringCustomer();
                Long clueId = saasFormSaveDTO.getClueId();
                if (Objects.nonNull(clueId) && clueId > 0) {
                    // 线索转换后需要更新线索状态为已转换,并设置已转换的客户id，方便市场活动统计线索的时候用
                    Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put(ClueEnum.CLUE_STATUS.getAttr(), ClueStatusEnum.TRANSFORMED.getCode());
                    ClueEntityExt clueEntityExt = clueModel.getByKey(clueId, corpid);
                    if (Objects.nonNull(clueEntityExt)) {
                        if (isNew) {
                            Boolean flag = proFormHelp.getClueSingleRuleList(corpid, ClueRuleSettingEnum.NEW_CUSTOMER_CREATE_TIME.getConfig(), clueEntityExt.getFormId());
                            if (flag) {
                                // 线索模板设计界面，更新最后跟进时间规则中的“线索转换新建的客户，取其创建时间更新”规则开启，才更新线索的最后跟进时间
                                param.put(ClueEnum.LAST_CONNECT_TIME.getAttr(), newPaasFormDataEntity.getAddTime());
                            }
                        }
                        clueModel.jsonsetNoSubById(corpid, clueId, param);
                        if (Objects.equals(isBringCustomer, 1)) {
                            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                            BoolQueryBuilder queryBuilder = boolQuery();
                            queryBuilder.filter(termQuery("corpid.keyword", corpid));
                            queryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
                            queryBuilder.filter(termQuery(CustomerCommunicateEnum.getEsAttr4Keyword(CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE), XbbRefTypeEnum.CLUE.getCode()));
                            queryBuilder.filter(termQuery(CustomerCommunicateEnum.getEsAttr4Keyword(CustomerCommunicateEnum.COMMUNICATE_BUSINESS), clueId));
                            queryBuilder.filter(termQuery("logType", 0));
                            queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE.getType()));
                            searchSourceBuilder.query(queryBuilder);
                            List<String> fieldList = new ArrayList<>();
                            fieldList.add(FieldTypeEnum.DATAID.getAlias());
                            List<PaasFormDataEntityExt> entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE, fieldList, null, null);
                            if (CollectionsUtil.isNotEmpty(entityExts)) {
                                List<Long> dataIds = new ArrayList<>();
                                entityExts.forEach(item -> dataIds.add(item.getDataId()));
                                Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                                map.put("corpid", corpid);
                                map.put("idIn", dataIds);
                                map.put("del", 0);
                                List<CustomerCommunicateEntityExt> entitys = customerCommunicateModel.findEntitys(map);
                                Long appId = 0L;
                                for (CustomerCommunicateEntityExt entityExt : entitys) {
                                    JSONObject data1 = entityExt.getData();
                                    data1.remove(CustomerCommunicateEnum.COMMUNICATE_BUSINESS_LINK_TEXT.getAttr());
                                    data1.remove(CustomerCommunicateEnum.COMMUNICATE_BUSINESS.getAttr());
                                    data1.remove(CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE.getAttr());
                                    data1.put(CustomerCommunicateEnum.CUSTOMER_NAME.getAttr(), dataId);
                                    data1.put(CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), customerName);
                                    entityExt.setOriginalId(entityExt.getDataId());
                                    entityExt.setId(null);
                                    appId = entityExt.getAppId();
                                }
                                if (CollectionsUtil.isNotEmpty(entityExts)) {
                                    // 复制线索的跟进记录给客户
                                    customerCommunicateModel.insertBatch(entitys);
                                    // 复制线索的跟进记录的评论带到客户跟进记录里
                                    Map<Long, Long> entityIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                                    entitys.forEach(item -> entityIdMap.put(item.getOriginalId(), item.getId()));
                                    Map<String,Object> paramMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                                    paramMap.put("corpid",corpid);
                                    paramMap.put("type",BusinessCommentEnum.CUSTOMER_COMMUNICATE.getCode());
                                    paramMap.put("appId",appId);
                                    paramMap.put("refIdIn",dataIds);
                                    paramMap.put("del",0);
                                    List<PaasCommentEntityExt> comments = paasCommentModel.findEntitys(paramMap);
                                    if (CollectionsUtil.isNotEmpty(comments)) {
                                        for (PaasCommentEntityExt comment : comments) {
                                            comment.setId(null);
                                            comment.setRefId(entityIdMap.get(comment.getRefId()));
                                        }
                                        paasCommentModel.insertBatch(comments);
                                    }
                                    // 复制线索的跟进记录的点赞带到客户跟进记录里
                                    Map<String,Object> likeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                                    likeMap.put("corpid", corpid);
                                    likeMap.put("appId",appId);
                                    likeMap.put("type",BusinessCommentEnum.CUSTOMER_COMMUNICATE.getCode());
                                    likeMap.put("refIdIn",dataIds);
                                    likeMap.put("del",0);
                                    List<LikeEntity> likeEntityList = likeModel.findEntitys(likeMap);
                                    if (CollectionsUtil.isNotEmpty(likeEntityList)) {
                                        for (LikeEntity likeEntity : likeEntityList) {
                                            likeEntity.setId(null);
                                            likeEntity.setRefId(entityIdMap.get(likeEntity.getRefId()));
                                        }
                                        likeModel.insertBatch(likeEntityList);
                                    }
                                }

                                // 线索转客户动态，没有联系人和跟进业务
                                List<DynamicDTO> dynamicDTOS = new ArrayList<>(entitys.size());
                                for (CustomerCommunicateEntityExt entityExt : entitys) {
                                    DynamicDTO dynamicDTO = DynamicDTO.initDynamicDTO(creatorId, CrmLogMemoConstant.DYNAMIC_USER_COMMUNICATE_ADD, BasicConstant.ZERO, DynamicDTO.initMemoHolder(creatorUserName), null, null);
                                    dynamicDTO.setCustomerId(dataId);
                                    dynamicDTO.setRefId(entityExt.getId());
                                    dynamicDTO.setRefBusinessType(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
                                    JSONObject data = entityExt.getData();
                                    dynamicDTO.setRefName(data.getString(CustomerCommunicateEnum.MEMO.getAttr()));
                                    dynamicDTO.setAddTime(entityExt.getAddTime());
                                    dynamicDTO.setUpdateTime(entityExt.getUpdateTime());
                                    dynamicDTOS.add(dynamicDTO);
                                }
                                dynamicDetailsHelper.insertDynamic(dynamicDTOS, corpid);

                            }
                        }
                    }
                    //评分更新(线索转化客户之后，会在此处修改线索状态)
                    scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE,corpid,clueId,null);
                }
            } catch (XbbException e) {
                LOG.error("线索转换客户，并将线索的跟进记录带到客户", e);
            }

            // 编辑客户的时候没有变更阶段但是修改了流失原因，则将流失原因更新到阶段记录中
            if (!isNew && !Objects.equals(reasonId, oldReasonId) && StringUtil.isNotEmpty(stageCode) && Objects.equals(stageCode, oldStageCode)) {
                customerStageLogHelp.updateStageLogReasonId(corpid, formId, dataId, stageCode, reasonId, wastageMemo);
            }

            try {
                //评分更新（客户的编辑，底层是走到这里。客户的导入比较特殊，是在另一处 ExcelImportServiceImpl.insert）
                PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
                BeanUtil.copyProperties(newPaasFormDataEntity,paasFormDataEntityExt);
                scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,dataId,paasFormDataEntityExt);
            } catch (Exception e) {
                LOG.error("e{}",e.getMessage());
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
        return afterSavePojo;
    }

    /**
     * 客户里关联新建联系人校验联系人
     *
     * @param corpid       公司id
     * @param contactArray 联系人数据
     * @param dataId       客户id
     * @param name         客户名称
     * @author feng.zheng
     * @date 2019/2/21 20:42
     */
    @Override
    public void verifyContact(String corpid, JSONArray contactArray, Long dataId, String name, ValidateDataDTO validateDataDTO) throws XbbException {
        JSONArray linkCustomerArray = new JSONArray();
        JSONObject linkCustomerObj = new JSONObject();
        linkCustomerObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        linkCustomerObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        linkCustomerArray.add(linkCustomerObj);
        // 获取联系人的解释和必要信息
        PaasFormExplainEntity contactFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.CONTACT.getCode(), corpid);
        Map<String, FieldAttrEntity> contactExplainMap = ExplainUtil.getExplainMap(contactFormExplainEntity.getExplains(), "");

        // fix: 19222 【客户管理】关联新建联系人，设置联系人名称不允许有重复值，但是新增的时候仍然能保存成功。
        // 不允许姓名重复时才做处理
        Integer noRepeat = contactExplainMap.get(ContactEnum.NAME.getAttr()).getNoRepeat();
        if (Objects.nonNull(noRepeat) && Objects.equals(1, noRepeat)){
            Set<String> contactNameSet = new HashSet<>();
            JSONArray contactAddArray = new JSONArray();
            contactArray.forEach(obj -> {
                JSONObject contactObj = (JSONObject) obj;
                // 排除删除联系人的情况，只做新增联系人时排重
                Integer operationFlag = contactObj.getInteger(StringConstant.OPERATION_FLAG);
                if (!Objects.equals(operationFlag, LinkAddOperationFlagEnum.DEL.getCode())) {
                    JSONObject contactData = contactObj.getJSONObject(StringConstant.JSON_DATA);
                    contactNameSet.add(contactData.getString(ContactEnum.NAME.getAttr()));
                    contactAddArray.add(contactObj);
                }
            });
            if (contactNameSet.size() < contactAddArray.size()){
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201033);
            }
        }
        // 若开启电话判重，进行处理
        FieldAttrEntity phoneAttrEntity = contactExplainMap.get(ContactEnum.PHONE.getAttr());
        Integer phoneRepeatFlag = phoneAttrEntity.getSubForm().getItems().get(1).getNoRepeat();
        String titleName = phoneAttrEntity.getAttrName();
        if (Objects.equals(phoneRepeatFlag, 1)) {
            HashSet<String> phoneNumSet = new HashSet<>();
            for (Object obj : contactArray) {
                JSONObject contactObj = (JSONObject) obj;
                Integer operationFlag = contactObj.getInteger(StringConstant.OPERATION_FLAG);
                // 排除删除联系人的情况，只做新增联系人时排重
                if (Objects.equals(operationFlag, LinkAddOperationFlagEnum.DEL.getCode())) {
                    break;
                }
                JSONObject contactData = contactObj.getJSONObject(StringConstant.JSON_DATA);
                JSONArray PhoneFormArr = contactData.getJSONArray(ContactEnum.PHONE.getAttr());
                if (CollectionsUtil.isEmpty(PhoneFormArr)) {
                    continue;
                }
                for (Object PhoneForm : PhoneFormArr) {
                    JSONObject phoneForm = (JSONObject) PhoneForm;
                    String contactPhone = phoneForm.getString("text_2");
                    if (phoneNumSet.contains(contactPhone)) {
                        throw new XbbException(ContactErrorCodeEnum.API_ERROR_204010, ContactErrorCodeEnum.API_ERROR_204010.getMsg(), titleName, contactPhone);
                    }
                    phoneNumSet.add(contactPhone);
                }
            }
        }

        // 联系人公共部分属性
        ValidateDataDTO contactValidateDataDTO = new ValidateDataDTO();
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = new SaasNeedRedundantAttrPojo();
        saasNeedRedundantAttrPojo.setIsRelationItem(1);
        BeanUtil.copyProperties(validateDataDTO, contactValidateDataDTO);
        BeanUtil.copyProperties(contactFormExplainEntity, contactValidateDataDTO);
        contactValidateDataDTO.setExplainMap(contactExplainMap);
        // 每个联系人的data和dataId赋值
        List<ValidateDataDTO> needAddValidateDataDTO = new ArrayList<>();
        List<ValidateDataDTO> needDelValidateDataDTO = new ArrayList<>();
        List<ValidateDataDTO> needUpdateValidateDataDTO = new ArrayList<>();
        List<String> contactPhoneList = new ArrayList<>();
        JSONArray newContactArr = new JSONArray();
        List<String> noRepeatAttr = new ArrayList<>();
        String labelAttr = null;
        Iterator<Map.Entry<String, FieldAttrEntity>> iterator = contactExplainMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, FieldAttrEntity> entry = iterator.next();
            if (Objects.equals(entry.getValue().getNoRepeat(), 1)) {
                noRepeatAttr.add(entry.getKey());
            }
            if (Objects.equals(entry.getValue().getFieldType(), FieldTypeEnum.LABEL.getType())) {
                labelAttr = entry.getValue().getAttr();
            }
        }
        Map<String, Long> delPhoneMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String,  Map<String, Long>> noRepeatMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        int contactNum = contactArray.size();
        // 联系人数据id集合,电话判重用
        Set<Long> contactDataIdSet = new HashSet<>();
        Map<String, Long> labelPojoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (StringUtil.isNotEmpty(labelAttr)) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("formId", contactFormExplainEntity.getFormId());
            param.put("corpid", contactFormExplainEntity.getCorpid());
            param.put("appId", contactFormExplainEntity.getAppId());
            param.put("del", DelEnum.NORMAL.getDel());
            List<LabelEntity> entitys = labelModel.findEntitys(param);
            entitys.forEach(item->{
                labelPojoMap.put(item.getName(), item.getId());
            });
        }
        for (Object obj : contactArray) {
            // 单个联系人数据
            JSONObject contactObj = (JSONObject) obj;
            // 表示编辑时数据是否被更改，被更改operationFlag为1,被删除operationFlag为2
            Integer operationFlag = contactObj.getInteger(StringConstant.OPERATION_FLAG);
            // 联系人的data数据
            JSONObject contactData = contactObj.getJSONObject(StringConstant.JSON_DATA);
            Long contactDataId = contactObj.getLong(StringConstant.DATA_ID);
            if (Objects.nonNull(contactDataId)) {
                contactDataIdSet.add(contactDataId);
            }
            if (StringUtil.isNotEmpty(labelAttr)) {
                String string = contactData.getString(labelAttr);
                if ( Objects.nonNull(string) ) {
                    String[] split = string.split(",");
                    JSONArray jsonArray = new JSONArray();
                    for (String s : split) {
                        if (Objects.nonNull(labelPojoMap.get(s))){
                            jsonArray.add(labelPojoMap.get(s));
                        }
                    }
                    contactData.put(labelAttr, jsonArray);
                }
            }
            if (Objects.equals(operationFlag, LinkAddOperationFlagEnum.DEL.getCode()) && Objects.nonNull(contactDataId)) {
                contactNum--;
                List<String> phoneListFromFormData = FastJsonHelper.getPhoneListFromFormData(contactData, ContactEnum.PHONE.getAttr());
                for (String phone : phoneListFromFormData) {
                    delPhoneMap.put(phone, contactDataId);
                }
                for (String attr : noRepeatAttr) {
                    Map<String, Long> noRepeatDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    if (noRepeatMap.containsKey(attr)) {
                        noRepeatDataMap = noRepeatMap.get(attr);
                    }
                    noRepeatDataMap.put(contactData.getString(attr), contactDataId);
                    noRepeatMap.put(attr, noRepeatDataMap);
                }
            }
        }
        // 只有一个联系人时，设置该联系人为主联系人
        if (1 == contactNum) {
            JSONObject contactObj = (JSONObject) contactArray.get(0);
            JSONObject data = contactObj.getJSONObject(StringConstant.JSON_DATA);
            data.put(ContactEnum.IS_MAIN.getAttr(), BasicConstant.ONE);
        }
        for (Object obj : contactArray) {
            // 单个联系人数据
            JSONObject contactObj = (JSONObject) obj;
            // 表示编辑时数据是否被更改，被更改operationFlag为1,被删除operationFlag为2
            Integer operationFlag = contactObj.getInteger(StringConstant.OPERATION_FLAG);
            // 联系人的data数据
            JSONObject contactData = contactObj.getJSONObject(StringConstant.JSON_DATA);
            Long contactDataId = contactObj.getLong(StringConstant.DATA_ID);
            contactValidateDataDTO.setDataId(contactDataId);
            contactValidateDataDTO.setSerialNo(contactObj.getString(FieldTypeEnum.SERIALNO.getAlias()));
            contactValidateDataDTO.setImportDelContact(null);

            // 去掉传来的关联客户属性来兼容新建 提前为了让审批数据格式一致
            contactData.remove(ContactEnum.CUSTOMER_NAME.getAttr());
            contactData.remove(ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr());
            contactData.put(ContactEnum.CUSTOMER_NAME.getAttr(), linkCustomerArray);
            contactValidateDataDTO.setData(contactData);
            saasNeedRedundantAttrPojo.setContactPhoneList(contactPhoneList);
            contactValidateDataDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPojo);
            ProSaveHelp.analyticalData(contactValidateDataDTO);
            List<String> phoneListFromFormData = FastJsonHelper.getPhoneListFromFormData(contactData, ContactEnum.PHONE.getAttr());
            if (Objects.isNull(contactDataId)) {
                for (String phone : phoneListFromFormData) {
                    if (delPhoneMap.containsKey(phone)) {
                        contactValidateDataDTO.setDataId(delPhoneMap.get(phone));
                        contactValidateDataDTO.setImportDelContact(1);
                    }
                }
                for (String attr : noRepeatAttr) {
                    if (MapUtils.isNotEmpty(noRepeatMap) &&  noRepeatMap.containsKey(attr)
                            && noRepeatMap.get(attr).containsKey(contactData.getString(attr))) {
                        contactValidateDataDTO.setDataId(noRepeatMap.get(attr).get(contactData.getString(attr)));
                        contactValidateDataDTO.setImportDelContact(1);
                    }
                }
            }
            try {
                // fix: 26324 【成功部】字段填写完整报错报错提示“联系人类型没有填写”
                //  如果联系人已经删除 就跳过此校验
                if (!Objects.equals(operationFlag, LinkAddOperationFlagEnum.DEL.getCode())){
                    contactValidateDataDTO.setContactDataIdSet(contactDataIdSet);
                    formDataValidateDataHelp.validateData(contactValidateDataDTO);
                }
            } catch (XbbException e) {
                if (Objects.equals(e.getCode(), SystemErrorCodeEnum.API_ERROR_100034.getCode())) {
                    throw new XbbException(ContactErrorCodeEnum.API_ERROR_204008);
                } else {
                    throw e;
                }
            }
            // bug-id：38576
            saasSaveHelp.beforeSave(contactValidateDataDTO);
            if (Objects.equals(contactValidateDataDTO.getImportDelContact(), 1)) {
                contactValidateDataDTO.setDataId(null);
            }
            contactPhoneList.addAll(phoneListFromFormData);

            if (contactDataId != null) {
                if (Objects.equals(operationFlag, LinkAddOperationFlagEnum.DEL.getCode())) {
                    ValidateDataDTO newDelContactDTO = new ValidateDataDTO();
                    BeanUtil.copyProperties(contactValidateDataDTO, newDelContactDTO);
                    needDelValidateDataDTO.add(newDelContactDTO);
                    continue;
                }
                // 没有更改的的联系人
                if (!Objects.equals(operationFlag, LinkAddOperationFlagEnum.EDIT.getCode())) {
                    continue;
                }
            }

            if (contactDataId != null) {
                ValidateDataDTO newUpdateContactDTO = new ValidateDataDTO();
                BeanUtil.copyProperties(contactValidateDataDTO, newUpdateContactDTO);
                needUpdateValidateDataDTO.add(newUpdateContactDTO);
            } else {
                ValidateDataDTO newAddContactDTO = new ValidateDataDTO();
                BeanUtil.copyProperties(contactValidateDataDTO, newAddContactDTO);
                needAddValidateDataDTO.add(newAddContactDTO);
            }
            newContactArr.add(contactData);
        }
        contactArray = newContactArr;
        SaasNeedRedundantAttrPojo customerPojo = new SaasNeedRedundantAttrPojo();
        customerPojo.setNeedAddValidateDataDTO(needAddValidateDataDTO);
        customerPojo.setNeedDelValidateDataDTO(needDelValidateDataDTO);
        customerPojo.setNeedUpdateValidateDataDTO(needUpdateValidateDataDTO);
        validateDataDTO.setSaasNeedRedundantAttrPoJo(customerPojo);
    }

    @Override
    public BaseVO focus(FocusDTO focusDTO) throws XbbException {
        Long dataId = focusDTO.getDataIdList().get(0);
        String corpid = focusDTO.getCorpid();
        String userId = focusDTO.getUserId();
        Boolean fromNew = Objects.equals(focusDTO.getFromNew(), BasicConstant.ONE);
        if (!fromNew) {
            // 因为重点客户新建的，代码放在线程里，所以这边不作这个校验
            CustomerEntityExt customerEntityExt = customerModel.getByKey(dataId, corpid);
            if (customerEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
            }
            if (customerEntityExt.getDel() > DelEnum.NORMAL.getDel() || Objects.equals(customerEntityExt.getData().getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr()), 1)) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201029);
            }
        }
        CustomerFocusEntity customerFocusEntity = customerFocusModel.getByCustomerId(dataId, userId, corpid);
        if (customerFocusEntity == null && focusDTO.getFocus() == 1) {
            customerFocusEntity = new CustomerFocusEntity();
            customerFocusEntity.setCorpid(corpid);
            customerFocusEntity.setCustomerId(dataId);
            customerFocusEntity.setUserId(userId);
            customerFocusEntity.setFocus(focusDTO.getFocus());
            customerFocusEntity.setAddTime((long) DateUtil.getInt());
            customerFocusEntity.setUpdateTime((long) DateUtil.getInt());
        } else {
            boolean isShare;
            try {
                isShare = companyConfigModel.hasBeenEnable(corpid, CompanyConfigEnum.SHARE_FOCUS_CUSTOEMR.getAlias(), BasicConstant.IS_USE.toString());
            } catch (XbbException e) {
                isShare = Objects.equals(CompanyConfigEnum.SHARE_FOCUS_CUSTOEMR.getValue(), BasicConstant.IS_USE.toString());
            }
            Integer focus = focusDTO.getFocus();
            if (isShare && focus == 0) {
                //重点共享,所有人员取关
                customerFocusModel.unFocusBatch(Collections.singletonList(dataId), corpid);
                return new BaseVO();
            }
            customerFocusEntity.setFocus(focus);
            customerFocusEntity.setUpdateTime((long) DateUtil.getInt());
        }
        customerFocusModel.save(customerFocusEntity);
        return new BaseVO();
    }

    /**
     * 客户名称实时查重
     *
     * @param repeatCommonConditionDTO 查重公用条件
     * @param customerName             客户名称
     * @author feng.zheng
     * @date 2019/2/19 21:41
     */
    @Override
    public FormDataRepeatVO checkRepeatForCustomerName(RepeatCommonConditionDTO repeatCommonConditionDTO, String customerName) throws XbbException {
        // 客户名称判重
        FormDataRepeatVO formDataRepeatVO = new FormDataRepeatVO();
        if (customerName == null) {
            return formDataRepeatVO;
        }
        FormDataRepeatDTO formDataRepeatDTO = new FormDataRepeatDTO();
        BeanUtil.copyProperties(repeatCommonConditionDTO, formDataRepeatDTO);
        // 拼接条件，产品id
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(CustomerManagementEnum.NAME.getAttr());
        conditionsEntityExt.setSymbol(ConditionEnum.LIKE.getSymbol());
        conditionsEntityExt.setValue(Arrays.asList(customerName));
        conditionsEntityExt.setFieldType(FieldTypeEnum.TEXT.getType());
        formDataRepeatVO = saasSaveHelp.repeatOnlyByConditions(formDataRepeatDTO, Arrays.asList(conditionsEntityExt));
        return formDataRepeatVO;
    }

    @Override
    public CustomerUpdateBatchVO customerUpdateBatch(CustomerUpdateBatchDTO customerUpdateBatchDTO) throws XbbException {
        CustomerUpdateBatchVO customerUpdateBatchVO = new CustomerUpdateBatchVO();
        try {
            String corpid = customerUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            List<CustomerUpdateDTO> customerUpdateList = customerUpdateBatchDTO.getCustomerList();
            if (Objects.nonNull(customerUpdateList) && !customerUpdateList.isEmpty()) {
                customerUpdateList.forEach((item)->{
                    updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
            }
            if (!updateList.isEmpty()) {
                customerModel.updateBatch(updateList, corpid);
                //快速编辑触发评分
                updateScore4BatchUpdate(corpid,updateList,customerUpdateBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("customerServiceImpl.customerUpdateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return customerUpdateBatchVO;
    }



    @Override
    public ListAppVO formatCustomerAppList(FormDataListDTO formDataListDTO, List<PaasFormDataEntityExt> esEntities, Integer totalCount) throws XbbException {
        List<AppListPojo> appListPojos = new ArrayList<>();
        String corpid = formDataListDTO.getCorpid();
        String userId = formDataListDTO.getUserId();
        Long formId = formDataListDTO.getFormId();
        Integer businessType =  formDataListDTO.getBusinessType();


        Integer subBusinessType = formDataListDTO.getSubBusinessType();
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        List<Long> idIn = new ArrayList<>();
        idIn.add(-1L);
        for (PaasFormDataEntityExt customer : esEntities) {
            idIn.add(customer.getDataId());
        }
        // 获取退字标签
        Map<Long, TagLinkEntity> tagMap = tagLinkModel.getPublicTagLink(corpid, idIn, XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode());
        // 转移标签
        Map<Long, TagLinkEntity> transferTagMap = tagLinkModel.getPublicTagLink(corpid, idIn, XbbRefTypeEnum.CUSTOMER_TRANSFER.getCode());

        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (paasFormExplainEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = formDataListDTO.getExplainMap();
        // TODO 将字段解释传入判断设置电话是否可见
        //Map<Integer, String> customerNamePhoneMap = customerModel.getNamePhoneMap(userEntity, esEntities, corpid, explainList);
        //有提醒的客户
        List<Long> pushNotifyList = new ArrayList<>();
        saasListHelp.getPushNotify(idIn, corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), pushNotifyList);

        boolean isShare;
        try {
            isShare = companyConfigModel.hasBeenEnable(corpid, CompanyConfigEnum.SHARE_FOCUS_CUSTOEMR.getAlias(), BasicConstant.IS_USE.toString());
        } catch (XbbException e) {
            isShare = Objects.equals(CompanyConfigEnum.SHARE_FOCUS_CUSTOEMR.getValue(), BasicConstant.IS_USE.toString());
        }
        List<Long> dataIdList;
        if (isShare){
            dataIdList = customerFocusModel.getShareCustomerIdList(corpid);
        }else {
            dataIdList = customerFocusModel.getNoShareCustomerIdList(userId,corpid);
        }
        Map<Long, Integer> focusMap = new HashMap<>(dataIdList.size());
        for (Long customerId : dataIdList) {
            focusMap.put(customerId, 1);
        }
        // 呼叫中心权限
        boolean isActiveCall = callCenterCommonService.isOpenCallDingTalk(corpid, userId);

        //协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Boolean isPublic = Objects.equals(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode(),subBusinessType);
        userTeamService.getUserIdMap(idIn,corpid,formDataListDTO.getBusinessType(),isPublic,mainUserMap,coUserMap);
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);

        for (PaasFormDataEntityExt customer : esEntities) {
            JSONObject data = customer.getData();
            Long customerId = customer.getDataId();
            Long dataId = customer.getDataId();
            Long appId = customer.getAppId();
            Long menuId = customer.getMenuId();
            String name = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");

            JSONObject superScript = new JSONObject();
            JSONObject others = new JSONObject();

            List<SummaryDataPoJo> summaryList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.SUMMARY_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<SummaryDataPoJo> lablesList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.LABELS_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<FormTitlePoJo> titleList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.TITLE_LIST, new JSONArray()).toJavaList(FormTitlePoJo.class);
            // 角标 -
            superScript.put("message", pushNotifyList.contains(customerId) ? 1 : 0);
            //非重点客户列表，添加已关注客户标记
            if(!Objects.equals(subBusinessType, XbbRefTypeEnum.CUSTOMER_FOCUS.getCode())){
                if (null != focusMap.get(customerId)) {
                    superScript.put("focus", 1);
                }
            }
            // isAchived为1代表归档，2代表未归档
            JSONObject tagData = customer.getTagData();
            if(Objects.equals(tagData.getInteger("isAchived"), 1)){
                superScript.put("archived", 1);
            }
            // 退字标签
            if(tagMap.containsKey(customerId)){
                superScript.put("back", tagMap.getOrDefault(customerId, new TagLinkEntity()));
            }
            // 转移标签
            if(Objects.nonNull(transferTagMap) && transferTagMap.containsKey(customerId)){
                superScript.put("transfer", transferTagMap.getOrDefault(customerId, new TagLinkEntity()));
            }
            Boolean activeAliyunCall = callCenterCommonService.isActiveAliyunCall(corpid, userId).IsActiveAliyunAndHasRole();
            boolean showAliyunCall = saasListHelp.checkShowCall(userEntity, explainMap, customer);
            if(activeAliyunCall&&showAliyunCall){
                superScript.put("activeAliyunCall", 1);
            }else{
                superScript.put("activeAliyunCall", 0);
            }

            // 附近客户加公海标签
            //其他,放入评分(在前面的查询列表时，已经处理过一次评分的值，这里直接拿出来)
            if(!marketManagementBusinessHelp.feeTypeIsStandardOrAppIsClosed(corpid) && scoreRuleService.haveEnabledScoreRule(corpid,formId)){
                others.put("score",data.get(CustomerManagementEnum.SCORE.getAttr()));
            }
            //最后跟进时间
            String lastConnectTimeStr = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), I18nMessageUtil.getMessage(StringConstant.NEVER_CONNECT));
            // 客户最后跟进时间格式标识
            if(Objects.nonNull(data.get(FormConfigEnum.CUSTOMER_LAST_CONNECT_TIME.getDbAlias()))){
                String lastConnectTime = data.get(FormConfigEnum.CUSTOMER_LAST_CONNECT_TIME.getDbAlias()).toString();
                if(Objects.equals(lastConnectTime, "0")){
                    String lastConnectTimeTemp = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), "0");
                    lastConnectTimeStr = DateUtil.getString(Long.valueOf(lastConnectTimeTemp) * 1000L, DateUtil.SDFYMDHM);
                }
            }

            // 当前数据的创建人、负责人、协同人、当前操作人
            handlerExplainDTO.setOwnerId(mainUserMap.get(customerId));
            handlerExplainDTO.setCoUserId(coUserMap.get(customerId));
            handlerExplainDTO.setCreatorId(customer.getCreatorId());
            boolean stageOpen = CommonHelp.ifStageOpen(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), explainMap, handlerExplainDTO);

            if (stageOpen) {
                String customerStageStr = ItemUtil.parseItemPoJoFromFormData2String(data, CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), "");
                if (!customerStageStr.isEmpty()) {
                    others.put("stage", customerStageStr);
                }
            }
            if(Objects.equals(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode(), subBusinessType)){
                others.put("isGrab",1);
            }
            boolean isShowCallCenterPhone = false;
            if (!Objects.equals(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode(), subBusinessType) || Objects.equals(XbbRefTypeEnum.CUSTOMER_DEAL.getCode(), subBusinessType)) {
                isShowCallCenterPhone = true;
            }
            boolean isShowCall = isActiveCall && isShowCallCenterPhone;
            if(isShowCall){
                saasListHelp.setCallPhone(userEntity, explainMap, customer, others);
            }
            others.put("isCallCenter", isActiveCall);
            //app系统关联数据展示需要 others 和 superScript
            data.put("others",others);
            data.put("superScript",superScript);
            String finalLastConnectTimeStr = lastConnectTimeStr;
            summaryList.forEach(item -> {
                if (Objects.equals(item.getAttr(), CustomerManagementEnum.LAST_CONNECT_TIME.getAttr())) {
                    item.setValue(Collections.singletonList(finalLastConnectTimeStr));
                } else if (Objects.equals(item.getAttr(), CustomerManagementEnum.ADDRESS.getAttr())) {
                    item.setAttrName(CustomerManagementEnum.ADDRESS.getAttrName());
                }
            });

            appListPojos.add(new AppListPojo(customerId, titleList, summaryList, superScript, lablesList, others, appId, menuId, formId, name,businessType,dataId));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(totalCount);
        return  listAppVO;
    }


    @Override
    public ListAppVO formatDuplicateCustomerAppList(CustomerCheckRepeatDTO customerCheckRepeatDTO) throws XbbException {
        String corpid = customerCheckRepeatDTO.getCorpid();
        String userId = customerCheckRepeatDTO.getUserId();
        List<AppListPojo> appListPojos = new ArrayList<>();
        // 公司是否开启了工作流
        boolean isOpenWorkflow = commonHelp.isOpenWorkFlow(corpid);
        customerCheckRepeatDTO.setIsOpenWorkflow(isOpenWorkflow);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = getDuplicateCustomer(customerCheckRepeatDTO);
        Map<Long, String> formName = paasFormService.getNameMap(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());

        List<Long> customerIdIn = new ArrayList<>();
        // 客户-表单映射关系
        Map<Long,Long> customerFormMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt entity : esEntities.getContent()) {
            customerIdIn.add(entity.getDataId());
            customerFormMap.put(entity.getDataId(),entity.getFormId());
        }
        //获取在公海分组中客户id
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(customerCheckRepeatDTO,userAndDepartmentGetDTO);
        Map<String,UserEntity> userEntityMap = userHelp.getUserMap(userAndDepartmentGetDTO);
        List<Long> customerIdInGroup = commonService.getCustomerIdInGroup(customerCheckRepeatDTO, customerIdIn,customerFormMap);
        Map<Long,List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        userTeamService.getUserIdMap(customerIdIn,corpid,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),false,mainUserMap,coUserMap);
        Set<String> permSet = customerCheckRepeatDTO.getLoginUser().getPermSet();
        List<ItemPoJo> customerStatusList = dictionaryService.getArrayList(DictionaryEnum.CUSTOMER_STATUS, corpid, null);
        Map<String,String> typeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ItemPoJo itemPoJo : customerStatusList){
            typeMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
        }
        List<PaasProcessDataEntity> paasProcessDataEntityList = new ArrayList<>();
        if (!isOpenWorkflow) {
            // 没有开启工作流的时候需要到流程数据表查询审批中数据
            paasProcessDataEntityList = paasProcessDataModel.getInApprovalDataByLikeCondition(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), CustomerManagementEnum.NAME.getAttr(), customerCheckRepeatDTO.getNameLike(), corpid, null);
        }
        boolean grabPermission = true;
        if (!permSet.contains(ProPermissionAliasEnum.CUSTOMER_GAIN.getAlias())) {
            grabPermission = false;
        }

        // 查询关闭联系电话的表单
        Map<Long, Integer> openPhoneMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("del",DelEnum.NORMAL.getDel());
        map.put("saasMark", BasicConstant.ONE);
        map.put("businessType", XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        List<PaasFormExplainEntity> paasFormEntityExtList = paasFormExplainModel.list(map);
        for(PaasFormExplainEntity item : paasFormEntityExtList){
            if(Objects.nonNull(item) && Objects.equals(item.getDel(), DelEnum.NORMAL.getDel())) {
                String explains = item.getExplains();
                if(Objects.nonNull(explains)) {
                    Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
                    if(explainMap != null){
                        FieldAttrEntity fieldAttrEntity = explainMap.get(CustomerManagementEnum.PHONE.getAttr());
                        openPhoneMap.put(item.getFormId(), BasicConstant.ONE);
                        if(Objects.nonNull(fieldAttrEntity) && (Objects.equals(fieldAttrEntity.getVisible(), BasicConstant.ZERO) || Objects.equals(fieldAttrEntity.getIsOpen(), BasicConstant.ZERO))){
                            // 只要有一个客户表单模版电话字段不可见，就去除电话字段模糊搜索
                            openPhoneMap.put(item.getFormId(), BasicConstant.ZERO);
                        }
                    }
                }
            }
        }

        for (PaasFormDataEntityExt customer : esEntities.getContent()) {
            List<SummaryDataPoJo> summaryList = new ArrayList<>();
            List<SummaryDataPoJo> lablesList = new ArrayList<>();
            List<FormTitlePoJo> titleList = new ArrayList<>();

            Long formId = customer.getFormId();
            // 当客户是电话查重且该表单电话字段关闭，直接过滤数据
            if(Objects.equals(customerCheckRepeatDTO.getRule(), CheckRepeatRuleEnum.PHONE.getCode()) &&
                    Objects.equals(openPhoneMap.get(formId), BasicConstant.ZERO)){
                continue;
            }
            Map<String,String> industryMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<ItemPoJo> industryList = dataDictionaryModel.getDictionaryList4Attr(CustomerManagementEnum.INDUSTRY.getSaasAttr(), corpid, formId);
            for (ItemPoJo itemPoJo : industryList){
                industryMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
            }

            List<ItemPoJo> scaleList = dataDictionaryModel.getDictionaryList4Attr(CustomerManagementEnum.SCALE.getSaasAttr(), corpid, formId);
            Map<String,String> scaleMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ItemPoJo itemPoJo : scaleList){
                scaleMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
            }

            List<ItemPoJo> isIndividualList = dataDictionaryModel.getDictionaryList4Attr(CustomerManagementEnum.IS_INDIVIDUAL.getSaasAttr(), corpid, formId);
            Map<String,String> isIndividualMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ItemPoJo itemPoJo : isIndividualList){
                isIndividualMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
            }

            JSONObject data = customer.getData();
            String name = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
            Integer isAchived = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_ARCHIVED.getAttr(), 0);
            Long customerId = customer.getDataId();
            Integer isPublic = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_PUBLIC.getAttr(), 0);
            boolean publicFlag = 1 == isPublic;
            JSONObject superScript = new JSONObject();
            JSONObject others = new JSONObject();

            summaryList.add(commonHelp.setSummary(I18nMessageUtil.getMessage(I18nStringConstant.CUSTOMER_TEMPLATE), formName.get(formId)));

            // 标签
            String type = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.TYPE.getAttr(), "");
            String typeStr = typeMap.getOrDefault(type, "");
            String scale = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.SCALE.getAttr(), "");
            String scaleStr = scaleMap.getOrDefault(scale, "");
            String isIndividual = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.IS_INDIVIDUAL.getAttr(), "");
            String isIndividualStr = isIndividualMap.getOrDefault(isIndividual, "");
            String industry = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.INDUSTRY.getAttr(), "");
            String industryStr = industryMap.getOrDefault(industry, "");

            if (!typeStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.TYPE.getAttrName(), typeStr));
            }
            if (!scaleStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.SCALE.getAttrName(), scaleStr));
            }
            if (!isIndividualStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.IS_INDIVIDUAL.getAttrName(), isIndividualStr));
            }
            if (!industryStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.INDUSTRY.getAttrName(), industryStr));
            }

            if(isAchived == 1){
                superScript.put("archived", BasicConstant.ONE);
            }

            boolean grab = true;
            boolean addTeam = true;
            List<String> mainUserIdList = mainUserMap.getOrDefault(customerId,new ArrayList<>());
            List<String> coUserIdList = coUserMap.getOrDefault(customerId,new ArrayList<>());
            if (Objects.equals(customer.getDel(),DelEnum.DELETE.getDel())){
                grab = false;
                addTeam = false;
            }else if (publicFlag){
                addTeam = false;
            }else if (mainUserIdList.contains(userId) || coUserIdList.contains(userId)){
                grab = false;
                addTeam = false;
            }else {
                grab = false;
            }
            //没有公海分组权限的客户
            if (!customerIdInGroup.contains(customerId)) {
                grab = false;
                addTeam = false;
            }
            // 判断有无 "查重-加入团队" 权限
            if (!permSet.contains(ProPermissionAliasEnum.CUSTOMER_REPEAT_JOIN_TEAM.getAlias())) {
                addTeam = false;
            }
            // 判断捞取权限
            if (!grabPermission) {
                grab = false;
            }
            if (grab) {
                others.put("isGrab", BasicConstant.ONE);
            }
            if (addTeam) {
                others.put("isAddTeam", BasicConstant.ONE);
            }
            StringBuilder stringBuilder = new StringBuilder();
            for (String mainUserId : mainUserIdList){
                UserEntity userEntity = userEntityMap.get(mainUserId);
                if (Objects.nonNull(userEntity)) {
                    StringUtil.stringBuilderAppendSuffix(stringBuilder,",",userEntity.getName());
                }
            }
            summaryList.add(commonHelp.setSummary(I18nMessageUtil.getMessage(CommonConstant.MAIN_USER), stringBuilder.toString()));
            String postion = commonService.getCustomerPostion(customer);
            lablesList.add(commonHelp.setLable(I18nMessageUtil.getMessage(I18nStringConstant.LOCATION), postion));

            titleList.add(commonHelp.setTitle(name));


            appListPojos.add(new AppListPojo(customerId, name, titleList, summaryList, superScript, lablesList, others, customer.getAppId(), customer.getMenuId(), customer.getFormId()));
        }
        for (PaasProcessDataEntity customer : paasProcessDataEntityList) {
            List<SummaryDataPoJo> summaryList = new ArrayList<>();
            List<SummaryDataPoJo> lablesList = new ArrayList<>();
            List<FormTitlePoJo> titleList = new ArrayList<>();

            Long formId = customer.getFormId();
            // 当客户是电话查重且该表单电话字段关闭，直接过滤数据
            if(Objects.equals(customerCheckRepeatDTO.getRule(), CheckRepeatRuleEnum.PHONE.getCode()) &&
                    Objects.equals(openPhoneMap.get(formId), BasicConstant.ZERO)){
                continue;
            }
            Map<String,String> industryMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<ItemPoJo> industryList = dataDictionaryModel.getDictionaryList4Attr(CustomerManagementEnum.INDUSTRY.getSaasAttr(), corpid, formId);
            for (ItemPoJo itemPoJo : industryList){
                industryMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
            }

            List<ItemPoJo> scaleList = dataDictionaryModel.getDictionaryList4Attr(CustomerManagementEnum.SCALE.getSaasAttr(), corpid, formId);
            Map<String,String> scaleMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ItemPoJo itemPoJo : scaleList){
                scaleMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
            }

            List<ItemPoJo> isIndividualList = dataDictionaryModel.getDictionaryList4Attr(CustomerManagementEnum.IS_INDIVIDUAL.getSaasAttr(), corpid, formId);
            Map<String,String> isIndividualMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ItemPoJo itemPoJo : isIndividualList){
                isIndividualMap.put(itemPoJo.getValue().toString(),itemPoJo.getText());
            }

            JSONObject data = JSONObject.parseObject(customer.getData());
            String name = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
            Integer isAchived = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_ARCHIVED.getAttr(), 0);
            Long customerId = customer.getId();
            Integer isPublic = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_PUBLIC.getAttr(), 0);
            boolean publicFlag = 1 == isPublic;
            JSONObject superScript = new JSONObject();
            JSONObject others = new JSONObject();

            summaryList.add(commonHelp.setSummary(I18nMessageUtil.getMessage(I18nStringConstant.CUSTOMER_TEMPLATE), formName.get(formId)));

            // 标签
            String type = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.TYPE.getAttr(), "");
            String typeStr = typeMap.getOrDefault(type, "");
            String scale = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.SCALE.getAttr(), "");
            String scaleStr = scaleMap.getOrDefault(scale, "");
            String isIndividual = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.IS_INDIVIDUAL.getAttr(), "");
            String isIndividualStr = isIndividualMap.getOrDefault(isIndividual, "");
            String industry = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.INDUSTRY.getAttr(), "");
            String industryStr = industryMap.getOrDefault(industry, "");

            if (!typeStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.TYPE.getAttrName(), typeStr));
            }
            if (!scaleStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.SCALE.getAttrName(), scaleStr));
            }
            if (!isIndividualStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.IS_INDIVIDUAL.getAttrName(), isIndividualStr));
            }
            if (!industryStr.isEmpty()) {
                lablesList.add(commonHelp.setLable(CustomerManagementEnum.INDUSTRY.getAttrName(), industryStr));
            }

            if(isAchived == 1){
                superScript.put("archived", BasicConstant.ONE);
            }

            List<String> mainUserIdList = mainUserMap.getOrDefault(customerId,new ArrayList<>());
            StringBuilder stringBuilder = new StringBuilder();
            for (String mainUserId : mainUserIdList){
                UserEntity userEntity = userEntityMap.get(mainUserId);
                StringUtil.stringBuilderAppendSuffix(stringBuilder,",",userEntity.getName());
            }
            summaryList.add(commonHelp.setSummary(I18nMessageUtil.getMessage(CommonConstant.MAIN_USER), stringBuilder.toString()));
           // String postion = commonService.getCustomerPostion(customer);
            //lablesList.add(commonHelp.setLable(I18nMessageUtil.getMessage(I18nStringConstant.LOCATION), postion));

            titleList.add(commonHelp.setTitle(name));

            Long formDataId = Objects.isNull(customer.getFormDataId()) ? 0 : customer.getFormDataId();
            appListPojos.add(new AppListPojo(formDataId, name, titleList, summaryList, superScript, lablesList, others, customer.getAppId(), customer.getMenuId(), customer.getFormId()));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount((int)esEntities.getTotalElements());
        return  listAppVO;
    }

    /**
     * 根据客户id队列查找符合要求的客户列表
     *
     * @param corpid      公司ID
     * @param customerIds 客户id列表
     * @return 客户集合
     */
    @Override
    public List<CustomerEntityExt> getCustomerListByIds(String corpid, List<Long> customerIds) throws XbbException {
        if (customerIds == null || customerIds.size() == 0) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(4);
        params.put("corpid", corpid);
        params.put("ids", customerIds);
        params.put("start", 0);
        params.put("pageNum", customerIds.size());
        return customerModel.findEntitys(params);
    }

    @Override
    public CustomerDeleteBatchVO deleteBatch(CustomerDeleteBatchDTO customerDeleteBatchDTO) throws XbbException {
        CustomerDeleteBatchVO customerDeleteBatchVO = new CustomerDeleteBatchVO();
        String corpid = customerDeleteBatchDTO.getCorpid();
        List<Long> customerCommunicateIdIn = new ArrayList<>();
        List<Long> invoiceIdIn = new ArrayList<>();
        List<Long> opportunityIdIn = new ArrayList<>();
        List<Long> contactIdIn = new ArrayList<>();
        List<Long> quotationIdIn = new ArrayList<>();
        Set<Long> deletePayMentBalanceId = new HashSet<>();
        List<Long> customerIdIn = customerDeleteBatchDTO.getDataIdList();
        /*if ( customerIdIn.size() > BasicConstant.MAX_DEL_BATCH_COUNT ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100079.getCode(),String.format(SystemErrorCodeEnum.API_ERROR_100079.getMsg(), BasicConstant.MAX_DEL_BATCH_COUNT));
        }*/
        try {
            // 过滤不允许删除的客户
            List<String> name = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> param = BeanUtil.convertBean2Map(customerDeleteBatchDTO, true);
            param.put("ids", customerIdIn);
            param.put("del", DelEnum.NORMAL.getDel());
            List<CustomerEntityExt> customerList = customerModel.findEntitys(param);
            if (Objects.isNull(customerList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            //兼容删除脏数据
            if (!Objects.equals(customerIdIn.size(), customerList.size())) {
                IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                BoolQueryBuilder builder = boolQuery();
                builder.filter(termQuery("corpid.keyword", corpid));
                builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                builder.filter(termsQuery(StringConstant.DATA_ID, customerIdIn));
                builder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                sourceBuilder.query(builder);
                searchRequest.source(sourceBuilder);
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, SizeConstant.PAGE_SIZE);
                XbbAggregatedPage<CustomerEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CustomerEntityExt.class);
                customerList = esEntities.getContent();
            }
            List<String> mergeNameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Long formId = 0L;
            for(CustomerEntityExt entityExt : customerList){
                JSONObject data = entityExt.getData();
                String customerName = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
                mergeNameList.add(customerName);
                formId = entityExt.getFormId();
            }
            if(Objects.isNull(customerDeleteBatchDTO.getFormId())) {
                customerDeleteBatchDTO.setFormId(formId);
            }
            String mergeNameStr = StringUtils.join(mergeNameList, "，");

            // 获取有合同的客户
            BoolQueryBuilder booleanQuery = boolQuery();
            String customerAttr = ContractEnum.LINK_CUSTOMER.getAttr();
            String customerContactAttr = ContactEnum.CUSTOMER_NAME.getAttr();
            String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
            booleanQuery.filter(termsQuery(linkCustomer, customerIdIn));
            booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            booleanQuery.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(linkCustomer);
            List<PaasFormDataEntityExt> contractList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTRACT, booleanQuery, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(contractList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            //客户对应的联系人进入审批
            Set<Long> hasContactCustomerID = new HashSet<>();
            if (commonHelp.isOpenWorkFlow(corpid)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME), customerIdIn));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_CONTACT.getType()));
                List<PaasFormDataEntityExt> contactFormDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT,
                        boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(ContactEnum.getAttrConnectData(ContactEnum.CUSTOMER_NAME), FieldTypeEnum.DATAID.getAlias()));
                contactFormDataList.forEach((item) -> {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(customerContactAttr)) && data.getLong(customerContactAttr) > 0L) {
                        hasContactCustomerID.add(data.getLong(customerContactAttr));
                    }
                });
            } else {
                List<PaasProcessDataEntity> approvalContactList = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.CONTACT.getCode(), ContactEnum.CUSTOMER_NAME.getAttr(), customerIdIn, corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                approvalContactList.forEach((item) -> {
                    JSONObject data = JSONObject.parseObject(item.getData());
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(customerContactAttr)) && data.getLong(customerContactAttr) > 0L) {
                        hasContactCustomerID.add(data.getLong(customerContactAttr));
                    }
                });
            }
            Set<Long> hasContractCustomerId = new HashSet<>();
            contractList.forEach((item)->{
                JSONObject data = item.getData();
                if (Objects.nonNull(data) && Objects.nonNull(data.get(customerAttr)) && data.getLong(customerAttr) > 0L) {
                    hasContractCustomerId.add(data.getLong(customerAttr));
                }
            });
            if (commonHelp.isOpenWorkFlow(corpid)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(ContractEnum.getEsAttr4Keyword(ContractEnum.LINK_CUSTOMER), customerIdIn));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_CONTRACT.getType()));
                List<PaasFormDataEntityExt> contractFormDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTRACT,
                        boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(ContractEnum.getAttrConnectData(ContractEnum.LINK_CUSTOMER), FieldTypeEnum.DATAID.getAlias()));
                contractFormDataList.forEach((item) -> {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(customerAttr)) && data.getLong(customerAttr) > 0L) {
                        hasContractCustomerId.add(data.getLong(customerAttr));
                    }
                });
            } else {
                List<PaasProcessDataEntity> approvalContractList = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.CONTRACT.getCode(), ContractEnum.LINK_CUSTOMER.getAttr(), customerIdIn, corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                approvalContractList.forEach((item) -> {
                    JSONObject data = JSONObject.parseObject(item.getData());
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(customerAttr)) && data.getLong(customerAttr) > 0L) {
                        hasContractCustomerId.add(data.getLong(customerAttr));
                    }
                });
            }
            Set<String> errorTypeSet = new HashSet<>();
            List<Long> allowDeleteCustomerId = new ArrayList<>();
            List<String> errorDataList = new ArrayList<>();
            UserVO loginUser = customerDeleteBatchDTO.getLoginUser();
            Boolean noPermission = !loginUser.isAdminOrBoss() && !loginUser.isMaxDataPermission();
            List<String> userIdIn = new ArrayList<>();
            if (noPermission) {
                UserEntity userEntity = new UserEntity();
                BeanUtil.copyProperties(loginUser, userEntity);
                Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), null);
                if (Objects.equals(dataPermission, DataPermissionEnum.SELF.getCode())) {
                    //数据权限为本人时
                    userIdIn = Collections.singletonList(loginUser.getUserId());
                } else {
                    //数据权限不为本人时，需要判断下属员工是否是负责人
                    userIdIn = userModel.getSubIdListByDataPermission(dataPermission, loginUser.getUserId(), loginUser.getCorpid(), BasicConstant.ONE, false);
                }
            }
            Set<Long> hasApprovalPaymentSheetCustomerId = new HashSet<>();
            if (commonHelp.isOpenWorkFlow(corpid)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(PaymentSheetEnum.getEsAttr4Keyword(PaymentSheetEnum.CUSTOMER_ID), customerIdIn));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET.getType()));
                List<PaasFormDataEntityExt> formDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET,
                        boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.CUSTOMER_ID), FieldTypeEnum.DATAID.getAlias()));
                formDataList.forEach(item -> {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(PaymentSheetEnum.CUSTOMER_ID.getAttr())) && data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr()) > 0L) {
                        hasApprovalPaymentSheetCustomerId.add(data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr()));
                    }
                });
            } else {
                List<PaasProcessDataEntity> approvalPaymentSheetList = paasProcessDataModel.getInApprovalDataByIdAndTypeCondition(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), PaymentSheetEnum.CUSTOMER_ID.getAttr(), customerIdIn, customerDeleteBatchDTO.getCorpid(), Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                approvalPaymentSheetList.forEach((item) -> {
                    JSONObject data = JSONObject.parseObject(item.getData());
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(PaymentSheetEnum.CUSTOMER_ID.getAttr())) && data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr()) > 0L) {
                        hasApprovalPaymentSheetCustomerId.add(data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr()));
                    }
                });
            }
            List<PaasFormDataEntityExt> paymentSheetList = paymentSheetService.getPaymentSheetEsDataListByCustomerIds(customerDeleteBatchDTO.getCorpid(),customerIdIn,Arrays.asList(PaymentSheetTypeEnum.RED_PREPAYMENT.getCode(),PaymentSheetTypeEnum.PREPAYMENT.getCode()));
            Set<Long> hasPaymentSheetCustomerId = new HashSet<>();
            paymentSheetList.forEach((item)->{
                JSONObject data = item.getData();
                if (Objects.nonNull(data) && Objects.nonNull(data.get(PaymentSheetEnum.CUSTOMER_ID.getAttr())) && data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr()) > 0L) {
                    hasPaymentSheetCustomerId.add(data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr()));
                }
            });
            Iterator iterator = customerList.iterator();
            while (iterator.hasNext()){
                // 判断审批中
                CustomerEntityExt item = (CustomerEntityExt) iterator.next();
                Long customerId = item.getId();
                if (hasContractCustomerId.contains(customerId)) {
                    // 含有合同的id
                    iterator.remove();
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(CustomerManagementEnum.NAME.getAttr()))){
                        errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_CONTRACT_NOT_DEL));
                        errorDataList.add(data.getString(CustomerManagementEnum.NAME.getAttr()));
                    }
                    continue;
                }
                if (hasContactCustomerID.contains(customerId)) {
                    // 有存在审批中联系人的id
                    iterator.remove();
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(CustomerManagementEnum.NAME.getAttr()))){
                        errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_CONTACT_NOT_DEL));
                        errorDataList.add(data.getString(CustomerManagementEnum.NAME.getAttr()));
                    }
                    continue;
                }
                if(CollectionsUtil.isNotEmpty(hasApprovalPaymentSheetCustomerId)){
                    if(hasApprovalPaymentSheetCustomerId.contains(customerId)){
                        iterator.remove();
                        JSONObject data = item.getData();
                        if (Objects.nonNull(data) && Objects.nonNull(data.get(CustomerManagementEnum.NAME.getAttr()))){
                            errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_P_M_B_NOT_DEL));
                            errorDataList.add(data.getString(CustomerManagementEnum.NAME.getAttr()));
                        }
                        continue;
                    }
                }
                if(CollectionsUtil.isNotEmpty(hasPaymentSheetCustomerId)){
                    if(hasPaymentSheetCustomerId.contains(customerId)){
                        iterator.remove();
                        JSONObject data = item.getData();
                        if (Objects.nonNull(data) && Objects.nonNull(data.get(CustomerManagementEnum.NAME.getAttr()))){
                            errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_PAYMENTSHEET_NOT_DEL));
                            errorDataList.add(data.getString(CustomerManagementEnum.NAME.getAttr()));
                        }
                        continue;
                    }
                }
                item.setDataId(customerId);
                Integer isPublic = FastJsonHelper.getIntegerOrDefaultFromFormData(item.getData(), CustomerManagementEnum.IS_PUBLIC.getAttr(), 0);
                // 除公海客户且不是最大的数据权限，自己或其下属不是负责人则不能删除该客户
                if (noPermission && !Objects.equals(isPublic, 1) && !saasDetailPermissionHelp.checkDelPermission(userIdIn, item, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                    iterator.remove();
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(CustomerManagementEnum.NAME.getAttr()))){
                        errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.NO_PERMISSION_CUSTOMER_DEL));
                        errorDataList.add(data.getString(CustomerManagementEnum.NAME.getAttr()));
                    }
                    continue;
                }
                allowDeleteCustomerId.add(customerId);
            }
            List<String> errorTypeList = new ArrayList<>(errorTypeSet);
            customerDeleteBatchVO.setErrorTypeList(errorTypeList);
            customerDeleteBatchVO.setErrorDataList(errorDataList);
            List<Long> isPublicCustomerIdIn = new ArrayList<>();
            if (!allowDeleteCustomerId.isEmpty()) {
                List<UpdateDataEntity> updateDataList = new ArrayList<>();
                allowDeleteCustomerId.forEach((item)->{
                    UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                    List<UpdateDataValueEntity> updateDataValueList = new ArrayList<>();
                    UpdateDataValueEntity isPublic = new UpdateDataValueEntity();
                    isPublic.setValue(1);
                    isPublic.setKey(CustomerManagementEnum.IS_PUBLIC.getAttr());
                    isPublic.setEsKey(CustomerManagementEnum.IS_PUBLIC.getAttr());
                    isPublicCustomerIdIn.add(item);
                    updateDataValueList.add(isPublic);
                    updateDataEntity.setId(item);
                    updateDataEntity.setCorpid(corpid);
                    long now = DateUtil.getInt();
                    updateDataEntity.setUpdateTime(now);
                    updateDataEntity.setData(updateDataValueList);
                    updateDataList.add(updateDataEntity);
                });

                //查询名称
                BoolQueryBuilder builder = boolQuery();
                builder.filter(termQuery("corpid.keyword", corpid));
                builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                builder.filter(termsQuery(StringConstant.DATA_ID, allowDeleteCustomerId));
                IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

                builder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, customerIndex.getType()));
                SearchRequest searchRequest = new SearchRequest(customerIndex.getIndex());
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                sourceBuilder.query(builder);
                searchRequest.source(sourceBuilder);
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, SizeConstant.PAGE_SIZE);
                XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
                List<PaasFormDataEntityExt> nameList = esEntities.getContent();
                if (!nameList.isEmpty()) {
                    for(PaasFormDataEntityExt entityExt : nameList){
                        JSONObject data = entityExt.getData();
                        String sheetName = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
                        name.add(sheetName);
                    }
                }

                if(!updateDataList.isEmpty()) {
                    if(BasicConstant.ONE.equals(customerDeleteBatchDTO.getSingleFlag())
                            && BasicConstant.ONE.equals(updateDataList.size())){
                        customerModel.updateBatch(updateDataList,corpid, WriteRequest.RefreshPolicy.NONE);
                    }else {
                        customerModel.updateBatch(updateDataList, corpid, WriteRequest.RefreshPolicy.NONE);
                    }
                }
                if (CollectionsUtil.isNotEmpty(allowDeleteCustomerId) && Objects.isNull(customerDeleteBatchDTO.getIsRemoveCompletely())) {
                    customerModel.deleteBatch(allowDeleteCustomerId, corpid, WriteRequest.RefreshPolicy.NONE);
                    marketActivityForStaticHelp.deleteBatchMarketActivity(allowDeleteCustomerId, XbbRefTypeEnum.CUSTOMER_MANAGEMENT ,corpid, BasicConstant.ONE);
                } else if (CollectionsUtil.isNotEmpty(allowDeleteCustomerId) && Objects.equals(customerDeleteBatchDTO.getIsRemoveCompletely(), BasicConstant.ONE)) {
                    customerModel.thoroughDeleteBatch(allowDeleteCustomerId, corpid, DelEnum.REMOVE_COMPLETELY.getDel());
                    FormDataThoroughDeleteDTO formDataThoroughDeleteDTO = new FormDataThoroughDeleteDTO();
                    BeanUtil.copyProperties(customerDeleteBatchDTO, formDataThoroughDeleteDTO);
                    formDataThoroughDeleteDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                    deleteCustomerCommunicate(formDataThoroughDeleteDTO, allowDeleteCustomerId);
                    // 这个会在之后统一处理
                    // deleteStaticMarket(corpid, allowDeleteCustomerId, BasicConstant.ONE);
                }
                // 删除负责人
                CustomerUserDeleteBatchDTO customerUserDeleteBatchDTO = new CustomerUserDeleteBatchDTO();
                BeanUtil.copyProperties(customerDeleteBatchDTO, customerUserDeleteBatchDTO);
                customerUserDeleteBatchDTO.setCustomerIdIn(allowDeleteCustomerId);
                customerUserService.deleteBatch(customerUserDeleteBatchDTO, WriteRequest.RefreshPolicy.NONE);
                Runnable runnable= () ->{
                    // 下午业务，异步删除
                    try {
                        // 取消关注
                        deleteCustomerFocus(customerDeleteBatchDTO, allowDeleteCustomerId);
                        // 删除发票
                        deleteInvoice(customerDeleteBatchDTO, allowDeleteCustomerId);

                        // 删除机会
                        deleteOpportunity(customerDeleteBatchDTO, allowDeleteCustomerId);
                        // 删除联系人
                        deleteContact(customerDeleteBatchDTO, allowDeleteCustomerId);
                        // 删除报价单
                        deleteQuotation(customerDeleteBatchDTO, allowDeleteCustomerId);
                        // 删除跟进记录 TODO 卡特说注释掉，在彻底删除时，删掉跟进记录
//                customerCommunicateIdIn = deleteCustomerCommunicate(customerDeleteBatchDTO, allowDeleteCustomerId);
                        //预收款余额表对应的删除
                        BoolQueryBuilder payMBQuery = boolQuery();
                        payMBQuery.filter(termsQuery(PaymentBalanceEnum.CUSTOMER_ID.getAttr(), customerIdIn));
                        payMBQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                        payMBQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                        List<PaymentBalanceEntity> payMentBalanceList = esHelper.findByScroll(IndexTypeEnum.IDX_PAYMENT_BALANCE, payMBQuery, PaymentBalanceEntity.class, Arrays.asList("id",PaymentBalanceEnum.CUSTOMER_ID.getAttr(),PaymentBalanceEnum.ADVANCE_PAYMENT_BALANCE.getAttr()));
                        //预收款余额等于0,存id
                        if(CollectionsUtil.isNotEmpty(payMentBalanceList)){
                            for (PaymentBalanceEntity paymentBalanceEntity : payMentBalanceList) {
                                deletePayMentBalanceId.add(paymentBalanceEntity.getId());
                            }
                        }
                        deletePayMentBalance(customerDeleteBatchDTO,new ArrayList<>(deletePayMentBalanceId));
                        PushNotifyDeleteDTO pushNotifyDeleteDTO = new PushNotifyDeleteDTO();
                        BeanUtil.copyProperties(customerDeleteBatchDTO, pushNotifyDeleteDTO);
                        pushNotifyDeleteDTO.setNeedDelNotifyIdList(allowDeleteCustomerId);
                        pushNotifyDeleteDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        pushNotifyService.deletePushNotify(pushNotifyDeleteDTO);
                        // 添加动态日志
                        if(!Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(),customerDeleteBatchDTO.getDistributorMark())) {
                            DynamicStrategy dynamicStrategy = dynamicStrategyFactory.getDynamicStrategy(ProjectLogEnum.CUSTOMER_DELETE.getSubType());
                            FormDataDeleteBatchDTO formDataDeleteBatchDTO = new FormDataDeleteBatchDTO();
                            BeanUtil.copyProperties(customerDeleteBatchDTO, formDataDeleteBatchDTO);
                            transactionHelp.afterCommitOrCommitNow(p -> {
                                dynamicStrategy.batchDelete(new DynamicDeleteDTO(formDataDeleteBatchDTO, allowDeleteCustomerId, null));
                            });
                        }
                    } catch (Exception e) {
                        LOG.error("删除客户动态失败：", e);
                    }

                };
                threadPoolBeanConfig.deleteFormData().execute(runnable);
            }
            customerDeleteBatchVO.setDeleteIds(allowDeleteCustomerId);
            customerDeleteBatchVO.setErrorDataList(errorDataList);
            customerDeleteBatchVO.setErrorTypeList(errorTypeList);
            customerDeleteBatchVO.setErrorDataMemo(SaasDeleteHelp.getErrorDataMemo(errorTypeList, errorDataList));
            //TODO 移除公海标签
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, customerDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = customerDeleteBatchDTO.getUserId();
            String userName = customerDeleteBatchDTO.getLoginUserName();
            String nameStr = StringUtils.join(name, "、");
            Integer singleFlag = customerDeleteBatchDTO.getSingleFlag();
            if(Objects.equals(0,singleFlag)||allowDeleteCustomerId.size() > 1){
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                DeleteBatchOperationLogDTO deleteBatchOperationLogDTO = new DeleteBatchOperationLogDTO( corpid,  userId,  userName, null,  operateTypeEnum,
                        null,  nameStr,  null,  allowDeleteCustomerId.size(),customerDeleteBatchDTO.getHttpHeader(),customerDeleteBatchDTO.getFormId(),customerDeleteBatchDTO.getBusinessType());
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                operationLogHandle.deleteBatch(infoArrPojoList,deleteBatchOperationLogDTO);
            } else if (Objects.equals(1,singleFlag)&&CollectionsUtil.isNotEmpty(allowDeleteCustomerId)){
                // 防止极端情况nameStr为空，主要来自合并客户
                nameStr = nameStr == "" ? mergeNameStr : nameStr;
                DeleteOperationLogDTO deleteOperationLogDTO = new DeleteOperationLogDTO(corpid,userId,userName,null,operateTypeEnum,allowDeleteCustomerId.get(0).toString(),nameStr,null,customerDeleteBatchDTO.getHttpHeader(),customerDeleteBatchDTO.getFormId(),customerDeleteBatchDTO.getBusinessType());
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                operationLogHandle.delete(deleteOperationLogDTO);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            updateRollback(customerDeleteBatchDTO.getDataIdList(), corpid);
            LOG.error("customerServiceImpl.deleteBatch 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return customerDeleteBatchVO;
    }


    public CustomerDeleteBatchVO mergeCustomerDeleteBatch(CustomerDeleteBatchDTO customerDeleteBatchDTO) throws XbbException {
        CustomerDeleteBatchVO customerDeleteBatchVO = new CustomerDeleteBatchVO();
        String corpid = customerDeleteBatchDTO.getCorpid();
        List<Long> customerIdIn = customerDeleteBatchDTO.getDataIdList();
        try {
            IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
            List<String> name = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> param = BeanUtil.convertBean2Map(customerDeleteBatchDTO, true);
            param.put("ids", customerIdIn);
            param.put("del", DelEnum.NORMAL.getDel());
            List<CustomerEntityExt> customerList = customerModel.findEntitys(param);
            //兼容删除脏数据
            if (!Objects.equals(customerIdIn.size(), customerList.size())) {
                BoolQueryBuilder builder = boolQuery();
                builder.filter(termQuery("corpid.keyword", corpid));
                builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                builder.filter(termsQuery(StringConstant.DATA_ID, customerIdIn));
                builder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, customerIndex.getType()));
                SearchRequest searchRequest = new SearchRequest(customerIndex.getIndex());
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                sourceBuilder.query(builder);
                searchRequest.source(sourceBuilder);
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, SizeConstant.PAGE_SIZE);
                XbbAggregatedPage<CustomerEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CustomerEntityExt.class);
                customerList = esEntities.getContent();
            }
            List<Long> deleteCustomerId = customerList.stream().map(CustomerEntityExt::getId).collect(Collectors.toList());
            List<String> mergeNameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(CustomerEntityExt entityExt : customerList){
                JSONObject data = entityExt.getData();
                String customerName = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
                mergeNameList.add(customerName);
            }
            String mergeNameStr = StringUtils.join(mergeNameList, "，");

            if (!deleteCustomerId.isEmpty()) {
                List<UpdateDataEntity> updateDataList = new ArrayList<>();
                deleteCustomerId.forEach((item)->{
                        UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                        List<UpdateDataValueEntity> updateDataValueList = new ArrayList<>();
                        UpdateDataValueEntity isPublic = new UpdateDataValueEntity();
                        isPublic.setValue(1);
                        isPublic.setKey(CustomerManagementEnum.IS_PUBLIC.getAttr());
                        isPublic.setEsKey(CustomerManagementEnum.IS_PUBLIC.getAttr());
                        updateDataValueList.add(isPublic);
                        updateDataEntity.setId(item);
                        updateDataEntity.setCorpid(corpid);
                        long now = DateUtil.getInt();
                        updateDataEntity.setUpdateTime(now);
                        updateDataEntity.setData(updateDataValueList);
                        updateDataList.add(updateDataEntity);
                    });

                //查询名称
                BoolQueryBuilder builder = boolQuery();
                builder.filter(termQuery("corpid.keyword", corpid));
                builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                builder.filter(termsQuery(StringConstant.DATA_ID, deleteCustomerId));
                builder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,customerIndex.getType()));
                SearchRequest searchRequest = new SearchRequest(customerIndex.getIndex());
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                sourceBuilder.query(builder);
                searchRequest.source(sourceBuilder);
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, SizeConstant.PAGE_SIZE);
                XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
                List<PaasFormDataEntityExt> nameList = esEntities.getContent();
                if (!nameList.isEmpty()) {
                    for(PaasFormDataEntityExt entityExt : nameList){
                        JSONObject data = entityExt.getData();
                        String sheetName = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
                        name.add(sheetName);
                    }
                }

                if(!updateDataList.isEmpty()) {
                    if(BasicConstant.ONE.equals(customerDeleteBatchDTO.getSingleFlag())
                            && BasicConstant.ONE.equals(updateDataList.size())){
                        customerModel.updateBatch(updateDataList,corpid, WriteRequest.RefreshPolicy.NONE);
                    }else {
                        customerModel.updateBatch(updateDataList, corpid);
                    }
                }
                if (CollectionsUtil.isNotEmpty(deleteCustomerId) && Objects.equals(customerDeleteBatchDTO.getIsRemoveCompletely(), BasicConstant.ONE)) {
                    customerModel.thoroughDeleteBatch(deleteCustomerId, corpid, DelEnum.REMOVE_COMPLETELY.getDel());
                    FormDataThoroughDeleteDTO formDataThoroughDeleteDTO = new FormDataThoroughDeleteDTO();
                    BeanUtil.copyProperties(customerDeleteBatchDTO, formDataThoroughDeleteDTO);
                    formDataThoroughDeleteDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                    deleteCustomerCommunicate(formDataThoroughDeleteDTO, deleteCustomerId);
                    // 这个会在之后统一处理
                    // deleteStaticMarket(corpid, allowDeleteCustomerId, BasicConstant.ONE);
                }
            }
            customerDeleteBatchVO.setDeleteIds(deleteCustomerId);
            //TODO 移除公海标签
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, customerDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = customerDeleteBatchDTO.getUserId();
            String userName = customerDeleteBatchDTO.getLoginUserName();
            String nameStr = StringUtils.join(name, "，");
            if(deleteCustomerId.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getName(), deleteCustomerId.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(CustomerManagementEnum.NAME.getAttrName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, operateTypeEnum,
                        "", "", memo, customerDeleteBatchDTO.getHttpHeader());
            } else if (Objects.equals(deleteCustomerId.size(), 1)){
                // 防止极端情况nameStr为空，主要来自合并客户
                nameStr = nameStr == "" ? mergeNameStr : nameStr;

                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, operateTypeEnum,
                        deleteCustomerId.get(0).toString(), nameStr, memo, customerDeleteBatchDTO.getHttpHeader());
            }
        } catch (Exception e) {
            updateRollback(customerDeleteBatchDTO.getDataIdList(), corpid);
            LOG.error("customerServiceImpl.deleteBatch 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return customerDeleteBatchVO;
    }



    @Override
    public CustomerEditAttrUpdateVO batchEditAttr(CustomerEditAttrUpdateDTO customerEditAttrUpdateDTO) throws XbbException {
        CustomerEditAttrUpdateVO customerEditAttrUpdateVO = new CustomerEditAttrUpdateVO();
        String userId = customerEditAttrUpdateDTO.getUserId();
        String corpid = customerEditAttrUpdateDTO.getCorpid();
        String loginUserName = customerEditAttrUpdateDTO.getLoginUserName();
        Integer isBatch = customerEditAttrUpdateDTO.getIsBatch();
        Long formId = customerEditAttrUpdateDTO.getFormId();
        Integer businessType = customerEditAttrUpdateDTO.getBusinessType();
        boolean isFieldDependence = customerEditAttrUpdateDTO.getIsFieldDependence();
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(customerEditAttrUpdateDTO, true);
            param.put("idIn", customerEditAttrUpdateDTO.getDataIdList());
            List<CustomerEntityExt> customerList = customerModel.findEntitys(param);
            if(Objects.isNull(customerList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            List<Long> updateIdList = new ArrayList<>();
            List<CustomerUpdateDTO> customerUpdateList = new ArrayList<>();
            customerEditAttrUpdateDTO.getDataIdList().forEach((item)->{
                CustomerUpdateDTO customerUpdateDTO = new CustomerUpdateDTO();
                customerUpdateDTO.setId(item);
                updateIdList.add(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(customerEditAttrUpdateDTO.getFieldEditedList());
                customerUpdateDTO.setData(data);
                customerUpdateList.add(customerUpdateDTO);
            });
            //需要判断公海池业务，如果是公海池业务就不需要走团队校验; 只需要拿第一条数据进行测试
            CustomerEntityExt customerEntityExt = customerList.get(BasicConstant.ZERO);
            Integer isPublic = customerEntityExt.getData().getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr());
            if (!Objects.equals(BasicConstant.ONE, isPublic)) {
                List<String> errorNameList = new ArrayList<>();
                //权限团队校验前置了
                List<Long> errorIdList = new ArrayList<>();
//                List<Long> errorIdList = userTeamHelp.batchTeamMembersCheckEditPermission(customerEditAttrUpdateDTO.getBusinessType(), customerEditAttrUpdateDTO.getSaasMark(),
//                        customerEditAttrUpdateDTO.getMenuId(), customerEditAttrUpdateDTO.getLoginUser(), customerEditAttrUpdateDTO.getDistributorMark(),
//                        customerEditAttrUpdateDTO.getDataIdList(), null);
                for (CustomerEntityExt customerEntityExtSen : customerList) {
                    if (errorIdList.contains(customerEntityExtSen.getDataId())) {
                        errorNameList.add(customerEntityExtSen.getData().getString(CustomerManagementEnum.NAME.getAttr()));
                    }
                }
                String nameStr = org.apache.commons.lang.StringUtils.join(errorNameList, "、");
                if (CollectionUtils.isNotEmpty(errorNameList)) {
                    throw new XbbException(UserTeamErrorCodeEnum.API_ERROR_271038.getCode(), String.format(UserTeamErrorCodeEnum.API_ERROR_271038.getMsg(), nameStr));
                }
            }
            AttrValuePojo singleAttrValuePojo = ProSaveHelp.getSingleAttrValuePojo(isFieldDependence, customerEditAttrUpdateDTO.getFieldEditedList());
            if (!customerUpdateList.isEmpty()) {
                List<String> AttrList = ProSaveHelp.getAttrList(customerEditAttrUpdateDTO.getFieldEditedList());
                CustomerUpdateBatchDTO customerUpdateBatchDTO = new CustomerUpdateBatchDTO();
                BeanUtil.copyProperties(customerEditAttrUpdateDTO, customerUpdateBatchDTO);
                customerUpdateBatchDTO.setCustomerList(customerUpdateList);
                customerUpdateBatchDTO.setFormId(customerEditAttrUpdateDTO.getFormId());
                customerUpdateBatchDTO.setAttrList(AttrList);
                customerUpdateBatch(customerUpdateBatchDTO);
                if (CustomerManagementEnum.TYPE.getAttr().equals(singleAttrValuePojo.getAttr())) {
                    // TODO 推送
                }
                customerEditAttrUpdateVO.setUpdateIdList(updateIdList);
            }
            // 触发客户分组先不要了

            // 批量编辑日志
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (CustomerEntityExt item : customerList) {
                dataIdList.add(item.getId());
            }
            if(Objects.nonNull(isBatch)){
                List<CustomerEntityExt> newCustomerList = customerModel.findEntitys(param);
                List<PaasFormDataEntity> newDataList = new ArrayList<>();
                List<PaasFormDataEntity> oldDataList = new ArrayList<>();
                BeanUtil.copyPropertiesList(customerList,oldDataList,PaasFormDataEntity.class);
                BeanUtil.copyPropertiesList(newCustomerList,newDataList,PaasFormDataEntity.class);
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(customerEditAttrUpdateDTO.getSaasMark(),customerEditAttrUpdateDTO.getBusinessType());
                UpdateBatchOperationLogDTO updateBatchOperationLogDTO = new UpdateBatchOperationLogDTO( corpid, userId, loginUserName, dataIdList.size(), customerEditAttrUpdateDTO.getHttpHeader(),
                        customerEditAttrUpdateDTO.getLogFieldEditedList(),newDataList, oldDataList, formId, businessType, isBatch);;
                operationLogHandle.updateBatch(updateBatchOperationLogDTO);
            }
        } catch (XbbException e){
            throw e;
        } catch (Exception e) {
            LOG.error("customerServiceImpl.batchEditAttr 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return customerEditAttrUpdateVO;
    }

    @Override
    public BaseVO changeStatus(ChangeStatusDTO changeStatusDTO) throws XbbException {
        // TODO 客户编辑权限校验
        Long dataId = changeStatusDTO.getDataId();
        Integer businessType = changeStatusDTO.getBusinessType();
        String corpid = changeStatusDTO.getCorpid();
        PaasFormDataEntityExt paasFormDataEntityExt = saasGetHelp.getFormData(dataId, corpid, businessType);
        if (paasFormDataEntityExt == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        JSONObject customerData = paasFormDataEntityExt.getData();
        /*SaasAnalysisDataDTO saasAnalysisDataDTO = new SaasAnalysisDataDTO();
        BeanUtil.copyProperties(changeStatusDTO, saasAnalysisDataDTO);
        // saas特殊格式转换
        saasUpdateHelp.formatData(saasAnalysisDataDTO, customerData);*/
        String type = changeStatusDTO.getType();
        String oldType = FastJsonHelper.getStringOrDefaultFromFormData(customerData, CustomerManagementEnum.TYPE.getAttr(), "");
        if (Objects.equals(oldType, type)) {
            throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201028);
        } else {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(CustomerManagementEnum.TYPE.getAttr(), type);
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
            customerModel.updateBatch(Collections.singletonList(updateData), corpid);
            /*customerData.put(CustomerManagementEnum.TYPE.getAttr(), type);
            FormDataUpdateDTO formDataUpdateDTO = new FormDataUpdateDTO();
            formDataUpdateDTO.setDataList(customerData);
            formDataUpdateDTO.setDataId(paasFormDataEntityExt.getId());
            formDataUpdateDTO.setCorpid(paasFormDataEntityExt.getCorpid());
            formDataUpdateDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
            formDataUpdateDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            BeanUtil.copyProperties(changeStatusDTO, formDataUpdateDTO);
            paasFormDataService.update(formDataUpdateDTO);*/

            Runnable runnable = () -> {
                try {
                    // 客户状态变更消息推送
                    String typeName = dataDictionaryModel.getDictionaryValue(corpid, DictionaryEnum.CUSTOMER_STATUS, type);
                    String customerName = customerData.getString(CustomerManagementEnum.NAME.getAttr());
                    List<String> customerUserIdList = customerUserModel.getCustomerUserIdList(corpid, Collections.singletonList(dataId), null);
                    List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CUSTOMER_CHANGE_PUSH.getCode(),
                            PushTypeEnum.CUSTOMER_CHANGE_PUSH.getSubCode(), changeStatusDTO.getLoginUser(), paasFormDataEntityExt);
                    pushUserList.addAll(customerUserIdList);
                    //去除当前操作人，可能在上一行中加回来。。。
                    pushUserList.remove(changeStatusDTO.getLoginUser().getUserId());
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), changeStatusDTO.getBusinessType(), changeStatusDTO.getBusinessType());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STATUS_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STATUS_CHANGE_CONTENT), changeStatusDTO.getLoginUserName(), customerName, typeName), null, options);
                    baseProducer.sendMessage(PushTypeEnum.CUSTOMER_CHANGE_PUSH, messageRabbitMqDTO);
                    //评分更新(客户状态变更)
                    scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,dataId,null);
                } catch (Exception e) {
                    LOG.error("客户状态变更消息推送", e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);

            // TODO 动态去除客户标签
            // 日志
            operationLogHelp.changeStatusLog(changeStatusDTO,paasFormDataEntityExt,updateData.getUpdateTime());
        }
        return new BaseVO();
    }

    /**
     * 触发客户分组
     * @author 吴峰
     * @date 2019/3/19 14:37
     * @param customerEditAttrUpdateDTO 前端传参
     * @param customerList 客户列表
     * @return void
     * @throws XbbException 业务异常
     */
    @Deprecated
    private void changeGroup(CustomerEditAttrUpdateDTO customerEditAttrUpdateDTO, List<CustomerEntityExt> customerList) {
        Long formId = customerEditAttrUpdateDTO.getFormId();
            List<Long> isPublicList = new ArrayList<>();
            Map<Long, CustomerEntityExt> customerMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (CustomerEntityExt item: customerList) {
                JSONObject data = item.getData();
                Boolean notPublicFlag = Objects.isNull(data) || Objects.isNull(data.get(CustomerManagementEnum.IS_PUBLIC.getAttr()))
                        || data.getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr()) != 1;
                if (notPublicFlag) {
                    continue;
                }
                isPublicList.add(item.getId());
                customerMap.put(item.getId(), item);
            }
            if (!isPublicList.isEmpty()) {
                CustomerChangeGroupDTO customerChangeGroupDTO = new CustomerChangeGroupDTO();
                BeanUtil.copyProperties(customerEditAttrUpdateDTO, customerChangeGroupDTO);
                customerChangeGroupDTO.setCustomerIdIn(isPublicList);
                customerChangeGroupDTO.setCustomerMap(customerMap);
            }
    }

    /**
     * 删除跟进记录
     * @author 吴峰
     * @date 2019/3/14 16:44
     * @param formDataThoroughDeleteDTO 前端传参
     * @param allowDeleteCustomerId 需要删除的客户id
     * @return void
     * @throws XbbException 业务异常
     */
    @Override
    public List<Long> deleteCustomerCommunicate(FormDataThoroughDeleteDTO formDataThoroughDeleteDTO, List<Long> allowDeleteCustomerId) throws XbbException {

        String corpid = formDataThoroughDeleteDTO.getCorpid();
        List<Long> customerCommunicateIdIn = new ArrayList<>();
        try {
            if (CollectionsUtil.isEmpty(allowDeleteCustomerId)) {
                return new ArrayList<>();
            }
            CustomerCommunicateDeleteBatchDTO customerCommunicateDeleteBatchDTO = new CustomerCommunicateDeleteBatchDTO();
            BeanUtil.copyProperties(formDataThoroughDeleteDTO, customerCommunicateDeleteBatchDTO, true);
            Runnable runnable = () -> {
                try {
                    List<Long> deleteIdIn = new ArrayList<>();
                    allowDeleteCustomerId.forEach(item->{
                        if (Objects.nonNull(item)) {
                            deleteIdIn.add(item);
                        }
                    });
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    CustomerCommunicateEnum anEnum = CustomerCommunicateEnum.CUSTOMER_NAME;
                    if (Objects.equals(formDataThoroughDeleteDTO.getBusinessType(), XbbRefTypeEnum.CLUE.getCode())) {
                        anEnum = CustomerCommunicateEnum.COMMUNICATE_BUSINESS;
                        boolQueryBuilder.filter(termQuery(CustomerCommunicateEnum.getEsAttr4Keyword(CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE), XbbRefTypeEnum.CLUE.getCode()));
                    }
                    boolQueryBuilder.filter(termsQuery(CustomerCommunicateEnum.getEsAttr4Keyword(anEnum), deleteIdIn));
                    boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    List<String> fieldList = new ArrayList<>();
                    fieldList.add(StringConstant.DATA_ID);
                    List<PaasFormDataEntityExt> customerCommunicateList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                    if (Objects.isNull(customerCommunicateList)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                    }
                    customerCommunicateList.forEach((item)->{
                        customerCommunicateIdIn.add(item.getDataId());
                    });
                    Integer allTotal = customerCommunicateList.size();
                    Integer pageSize = 100;
                    Integer index = allTotal/pageSize + 1;
                    Integer page = 0;
                    Integer toIndex = 100;
                    for (int j = 0; j < index; j++) {
                        if (toIndex > allTotal) {
                            toIndex = allTotal;
                        }
                        List<PaasFormDataEntityExt> resultList = customerCommunicateList.subList(page, toIndex);
                        if (CollectionsUtil.isNotEmpty(resultList)) {
                            List<Long> deleteList = new ArrayList<>();
                            resultList.forEach((item)->{
                                deleteList.add(item.getDataId());
                            });
                            customerCommunicateDeleteBatchDTO.setIdIn(deleteList);
                            customerCommunicateDeleteBatchDTO.setSingleFlag(null);
                            customerCommunicateService.deleteBatch(customerCommunicateDeleteBatchDTO);
                            page = page + pageSize;
                            toIndex = page + pageSize;
                        }
                    }
                } catch (Exception e) {
                    LOG.error("customerServiceImpl.deleteCustomerCommunicate 执行出错：", e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);


        } catch (Exception e) {
            LOG.error("customerServiceImpl.deleteCustomerCommunicate 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return customerCommunicateIdIn;
    }

    @Override
    public void dataConsistencyUpdateClue(String corpid, Long dataId, String companyName) throws XbbException{
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery(CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.CLUE_ID), dataId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(customerIndex, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<CustomerEntityExt> customerEntityExts = customerModel.findEntitys(param);
            if (Objects.nonNull(customerEntityExts) && !customerEntityExts.isEmpty()) {
                List<CustomerUpdateDTO> customerUpdateDTOS = new ArrayList<>();
                for (CustomerEntityExt entityExt : customerEntityExts) {
                    JSONObject oldData = entityExt.getData();
                    if (oldData == null) {
                        continue;
                    }
                    List<Long> idList = FastJsonHelper.getJsonArrOrDefaultFromFormData(oldData, CustomerManagementEnum.CLUE_ID.getAttr(), new JSONArray()).toJavaList(Long.class);
                    List<String> nameList = FastJsonHelper.getJsonArrOrDefaultFromFormData(oldData, CustomerManagementEnum.CLUE_NAME_ID.getAttr(), new JSONArray()).toJavaList(String.class);
                    for (int i = 0; i < idList.size(); i++) {
                        Long cid = idList.get(i);
                        if (Objects.equals(cid, dataId)) {
                            nameList.set(i, companyName);
                        }
                    }

                    CustomerUpdateDTO customerUpdateDTO = new CustomerUpdateDTO();
                    customerUpdateDTO.setId(entityExt.getId());
                    JSONObject data = new JSONObject();
                    data.put(CustomerManagementEnum.CLUE_NAME_ID.getAttr(), nameList);
                    customerUpdateDTO.setData(data);
                    customerUpdateDTOS.add(customerUpdateDTO);
                }
                CustomerUpdateBatchDTO customerUpdateBatchDTO = new CustomerUpdateBatchDTO();
                customerUpdateBatchDTO.setCorpid(corpid);
                customerUpdateBatchDTO.setCustomerList(customerUpdateDTOS);
                updateBatch(customerUpdateBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("CustomerServiceImpl.dataConsistencyUpdateClue fail， corpid=" + corpid + " clueId=" + dataId + "  companyName=" + companyName, e);
        }
    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = newPaasFormDataEntity.getId();
        Boolean isNew = saasFormSaveDTO.getIsNew();
        if (Objects.isNull(saasFormSaveDTO.getOwnerId()) || (Objects.nonNull(saasFormSaveDTO.getOwnerId()) && saasFormSaveDTO.getOwnerId().isEmpty())) {
            saasFormSaveDTO.setSubBusinessType(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode());
        }
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo();
        if (Objects.nonNull(saasNeedRedundantAttrPoJo)) {
            // 团队保存
            teamDataHelp.saveUserTeam(saasNeedRedundantAttrPoJo, dataId, newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), true);
        }
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONObject oldData = saasFormSaveDTO.getOldData();
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = newPaasFormDataEntity.getId();
        Boolean isNew = saasFormSaveDTO.getIsNew();
        if (Objects.isNull(saasFormSaveDTO.getOwnerId()) || (Objects.nonNull(saasFormSaveDTO.getOwnerId()) && saasFormSaveDTO.getOwnerId().isEmpty())) {
            saasFormSaveDTO.setSubBusinessType(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode());
        }

        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo();
        if (Objects.nonNull(saasNeedRedundantAttrPoJo)) {
            // 团队保存
            teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), saasFormSaveDTO.getNewPaasFormDataEntity().getId(), newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), true);
        }
    }

    /**
     * 处理客户脚本
     * @author lijiangren
     * @date 2022-05-26 10 52
     * @since
     * @version
     */
    @Override
    public void updateBatch4Script(List<SpecialUpdateCustomerDataEntity> updateDataEntityList) throws XbbException{
        if (CollectionsUtil.isNotEmpty(updateDataEntityList)) {
            customerModel.updateBatch4Script(updateDataEntityList);
        }
    }

    /**
     * 删除联系人
     * @author 吴峰
     * @date 2019/3/14 16:44
     * @param customerDeleteBatchDTO 前端传参
     * @param allowDeleteCustomerId 需要删除的客户id
     * @return void
     * @throws XbbException 业务异常
     */
    private List<Long> deleteContact(CustomerDeleteBatchDTO customerDeleteBatchDTO, List<Long> allowDeleteCustomerId) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        String corpid = customerDeleteBatchDTO.getCorpid();
        List<Long> contactIdIn = new ArrayList<>();
        try {
            boolQueryBuilder.filter(termsQuery(StringConstant.JSON_DATA + StringConstant.POINT+ ContactEnum.CUSTOMER_NAME.getAttr(), allowDeleteCustomerId));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            List<PaasFormDataEntityExt> contactList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(contactList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            contactList.forEach((item)->{
                contactIdIn.add(item.getDataId());
            });
            if (!contactIdIn.isEmpty()) {
                ContactDeleteBatchDTO contactDeleteBatchDTO = new ContactDeleteBatchDTO();
                BeanUtil.copyProperties(customerDeleteBatchDTO, contactDeleteBatchDTO, true);
                contactDeleteBatchDTO.setDataIdList(contactIdIn);
                contactService.deleteBatch(contactDeleteBatchDTO);
                ContactUserDeleteBatchDTO contactUserDeleteBatchDTO = new ContactUserDeleteBatchDTO();
                BeanUtil.copyProperties(customerDeleteBatchDTO, contactUserDeleteBatchDTO, true);
                contactUserDeleteBatchDTO.setContactIdIn(contactIdIn);
                contactUserService.deleteBatch(contactUserDeleteBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("customerServiceImpl.deleteContact 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return contactIdIn;
    }

    /**
     * 删除报价单
     * @author long.rao
     * @date 2019-09-29 17:13
     * @param customerDeleteBatchDTO 前端传参
     * @param allowDeleteCustomerId 需要删除的客户id
     * @return void
     * @throws XbbException 业务异常
     */
    private List<Long> deleteQuotation(CustomerDeleteBatchDTO customerDeleteBatchDTO, List<Long> allowDeleteCustomerId) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        String corpid = customerDeleteBatchDTO.getCorpid();
        List<Long> quotationIdIn = new ArrayList<>();
        try {
            boolQueryBuilder.filter(termsQuery(QuotationEnum.getEsAttr4Keyword(QuotationEnum.CUSTOMER_ID), allowDeleteCustomerId));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            List<PaasFormDataEntityExt> quotationList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_QUOTATION, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(quotationList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            quotationList.forEach((item)->{
                quotationIdIn.add(item.getDataId());
            });
            if (!quotationIdIn.isEmpty()) {
                QuotationDeleteBatchDTO quotationDeleteBatchDTO = new QuotationDeleteBatchDTO();
                BeanUtil.copyProperties(customerDeleteBatchDTO, quotationDeleteBatchDTO, true);
                quotationDeleteBatchDTO.setDataIdList(quotationIdIn);
                quotationDeleteBatchDTO.setFormId(null);
                quotationService.deleteBatch(quotationDeleteBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("customerServiceImpl.deleteQuotation 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return quotationIdIn;
    }

    /**
     * 删除机会
     * @author 吴峰
     * @date 2019/3/14 16:44
     * @param customerDeleteBatchDTO 前端传参
     * @param allowDeleteCustomerId 需要删除的客户id
     * @return void
     * @throws XbbException 业务异常
     */
    private List<Long> deleteOpportunity(CustomerDeleteBatchDTO customerDeleteBatchDTO, List<Long> allowDeleteCustomerId) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        String corpid = customerDeleteBatchDTO.getCorpid();
        List<Long> opportunityIdIn = new ArrayList<>();
        try {
            boolQueryBuilder.filter(termsQuery(StringConstant.JSON_DATA + StringConstant.POINT+ SalesOpportunityEnum.CUSTOMER_NAME.getAttr(), allowDeleteCustomerId));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            List<PaasFormDataEntityExt> opportunityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OPPORTUNITY, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(opportunityList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            opportunityList.forEach((item)->{
                opportunityIdIn.add(item.getDataId());
            });
            if (!opportunityIdIn.isEmpty()) {
                OpportunityDeleteBatchDTO opportunityDeleteBatchDTO = new OpportunityDeleteBatchDTO();
                BeanUtil.copyProperties(customerDeleteBatchDTO, opportunityDeleteBatchDTO, true);
                opportunityDeleteBatchDTO.setDataIdList(opportunityIdIn);
                // 不能把客户formid置为机会的formid
                opportunityDeleteBatchDTO.setFormId(null);
                opportunityService.deleteBatch(opportunityDeleteBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("customerServiceImpl.deleteOpportunity 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return opportunityIdIn;
    }

    /**
     * 删除发票
     * @author 吴峰
     * @date 2019/3/14 16:44
     * @param customerDeleteBatchDTO 前端传参
     * @param allowDeleteCustomerId 需要删除的客户id
     * @return void
     * @throws XbbException 业务异常
     */
    private List<Long> deleteInvoice(CustomerDeleteBatchDTO customerDeleteBatchDTO, List<Long> allowDeleteCustomerId) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        String corpid = customerDeleteBatchDTO.getCorpid();
        List<Long> invoiceIdIn = new ArrayList<>();
        try {
            boolQueryBuilder.filter(termsQuery(StringConstant.JSON_DATA + StringConstant.POINT+ InvoiceEnum.CUSTOMER_NAME.getAttr(), allowDeleteCustomerId));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            List<PaasFormDataEntityExt> invoiceList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INVOICE, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(invoiceList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            invoiceList.forEach((item)->{
                invoiceIdIn.add(item.getDataId());
            });
            if (!invoiceIdIn.isEmpty()) {
                InvoiceDeleteBatchDTO invoiceDeleteBatchDTO = new InvoiceDeleteBatchDTO();
                BeanUtil.copyProperties(customerDeleteBatchDTO, invoiceDeleteBatchDTO, true);
                invoiceDeleteBatchDTO.setDataIdList(invoiceIdIn);
                // 不能把客户formid置为发票的formid
                invoiceDeleteBatchDTO.setFormId(null);
                invoiceService.deleteBatch(invoiceDeleteBatchDTO, DelEnum.DELETE);
            }
        } catch (Exception e) {
            LOG.error("customerServiceImpl.deleteInvoice 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return invoiceIdIn;
    }

    /**
     * 删除预收款余额为0的记录
     * @param customerDeleteBatchDTO
     * @param deletePayMentBalanceId
     * @return
     * @throws XbbException
     */
    private List<Long> deletePayMentBalance(CustomerDeleteBatchDTO customerDeleteBatchDTO, List<Long> deletePayMentBalanceId) throws XbbException {
        if(CollectionsUtil.isEmpty(deletePayMentBalanceId)){
            return deletePayMentBalanceId;
        }
        try {
            paymentBalanceService.deleteBatch(deletePayMentBalanceId,customerDeleteBatchDTO.getCorpid());
        } catch (Exception e) {
            LOG.error("customerServiceImpl.deletePayMentBalance 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return deletePayMentBalanceId;
    }

    /**
     * 取消关注
     * @author 吴峰
     * @date 2019/3/14 16:28
     * @param customerDeleteBatchDTO
     * @param customerIdIn
     * @return void
     * @throws XbbException 业务异常
     */
    private void deleteCustomerFocus(CustomerDeleteBatchDTO customerDeleteBatchDTO, List<Long> customerIdIn) throws XbbException {
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(customerDeleteBatchDTO, true);
            param.put("customerIdIn", customerIdIn);
            param.put("del", DelEnum.NORMAL.getDel());
            List<CustomerFocusEntity> customerFocusList = customerFocusModel.findEntitys(param);
            if (Objects.isNull(customerFocusList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<Long> idIn = new ArrayList<>();
            for (CustomerFocusEntity item : customerFocusList) {
                idIn.add(item.getId());
            }
            if (!idIn.isEmpty()) {
                customerFocusModel.unFocusBatch(customerIdIn, customerDeleteBatchDTO.getCorpid());
            }
        } catch (Exception e) {
            LOG.error("customerServiceImpl.deleteCustomerFocus 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }
    @Override
    public BaseVO customerCardSet(CustomerCardDTO customerCardDTO) throws XbbException{
        String prefix = RedisPrefixConstant.BUZ_CARD_DATA;
        String key =  customerCardDTO.getCorpid() + ":" + customerCardDTO.getUserId();
        paasRedisHelper.setValue(prefix,key,JSONObject.toJSONString(customerCardDTO),RedisTimeConstant.SHORT_DURATION);
        return new BaseVO();
    }

    @Override
    public FormDataAddGetVO customerCardGet(BaseDTO baseDTO) throws XbbException{
        String prefix = RedisPrefixConstant.BUZ_CARD_DATA;
        String key =  baseDTO.getCorpid() + ":" + baseDTO.getUserId();
        CustomerCardDTO customerCardDTO = new CustomerCardDTO();
        customerCardDTO = JSONObject.parseObject(paasRedisHelper.getValue(prefix,key),customerCardDTO.getClass());
        FormDataAddGetDTO formDataAddGetDTO = new FormDataAddGetDTO();
        BeanUtil.copyProperties(customerCardDTO,formDataAddGetDTO);
        formDataAddGetDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        formDataAddGetDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        FormDataAddGetVO formDataAddGetVO = paasFormDataService.addGet(formDataAddGetDTO);
        List<FieldAttrEntity> explainList = formDataAddGetVO.getExplainList();
        boolean isCompany = Objects.equals(customerCardDTO.getCustomerType(),1);
        for (FieldAttrEntity fieldAttrEntity : explainList){
            DefaultAttrPoJo defaultAttrPoJo = fieldAttrEntity.getDefaultAttr();
            if (isCompany){
                if (Objects.equals(fieldAttrEntity.getAttr(),CustomerManagementEnum.NAME.getAttr())){
                    defaultAttrPoJo.setDefaultValue(customerCardDTO.getCompany());
                    fieldAttrEntity.setDefaultAttr(defaultAttrPoJo);
                }else if (Objects.equals(fieldAttrEntity.getAttr(),CustomerManagementEnum.WEBSITE.getAttr())){
                    defaultAttrPoJo.setDefaultValue(customerCardDTO.getWebsite());
                    fieldAttrEntity.setDefaultAttr(defaultAttrPoJo);
                }
            }else {
                if (Objects.equals(fieldAttrEntity.getAttr(),CustomerManagementEnum.NAME.getAttr())){
                    defaultAttrPoJo.setDefaultValue(customerCardDTO.getName());
                    fieldAttrEntity.setDefaultAttr(defaultAttrPoJo);
                }
            }
            if (Objects.equals(fieldAttrEntity.getAttr(),CustomerManagementEnum.PHONE.getAttr()) && !Objects.isNull(customerCardDTO.getPhone()) && !customerCardDTO.getPhone().isEmpty()){
                JSONObject phone = new JSONObject();
                JSONObject text1Obj = new JSONObject();
                text1Obj.put("text",PhoneExtEnum.WORK.getName());
                text1Obj.put("value",PhoneExtEnum.WORK.getCode());
                phone.put("text_1",text1Obj);
                phone.put("text_2",customerCardDTO.getPhone().getString(0));
                defaultAttrPoJo.setDefaultValue(Collections.singletonList(phone));
                fieldAttrEntity.setDefaultAttr(defaultAttrPoJo);
            }
            if (Objects.equals(fieldAttrEntity.getAttr(),CustomerManagementEnum.ADDRESS.getAttr())) {
                JSONObject geoObj = new JSONObject();
                try {
                    geoObj = GaodeGeoHelper.geo(customerCardDTO.getAddress(),"");
                } catch (Exception e) {
                    LOG.warn("地址转经纬度失败", e.getMessage());
                }
                AddressPojo addressPojo = new AddressPojo();
                addressPojo.setAddress(customerCardDTO.getAddress());
                if (geoObj != null && !geoObj.isEmpty()) {
                    addressPojo.setProvince(geoObj.getString("province"));
                    addressPojo.setCity(geoObj.getString("city"));
                    addressPojo.setDistrict(geoObj.getString("district"));
                    addressPojo.setLatAndLon(geoObj.getDouble("latitude"),geoObj.getDouble("longitude"));
                } else {
                    addressPojo.setProvince("");
                    addressPojo.setCity("");
                    addressPojo.setDistrict("");
                }
                defaultAttrPoJo.setDefaultValue(addressPojo);
                fieldAttrEntity.setDefaultAttr(defaultAttrPoJo);
            }
        }
        return formDataAddGetVO;
    }

    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList, Integer businessType) throws XbbException {
        String corpid = formDataListDTO.getCorpid();
        FieldAttrEntityForImport contactField = null;
        Integer customerShowPublicPool = 0;
        Integer customerPublicPool = 0;
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            if (Objects.equals(fieldAttrEntityForImport.getAttr(), CustomerManagementEnum.ADD_CONTACT.getAttr())) {
                contactField = fieldAttrEntityForImport;
                continue;
            }
            if (Objects.equals(fieldAttrEntityForImport.getAttr(), CustomerManagementEnum.PHONE.getAttr())) {
                customerShowPublicPool = fieldAttrEntityForImport.getShowPublicPool();
                customerPublicPool = fieldAttrEntityForImport.getPublicPool();
                continue;
            }
        }
        if (Objects.isNull(contactField)) {
            return;
        }
        List<Long> businessIdIn = new ArrayList<>();
        paasFormDataESList.forEach(paasFormDataEntityExt -> businessIdIn.add(paasFormDataEntityExt.getId()));
        String keyword = StringConstant.POINT + StringConstant.KEY_WORD;
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + keyword, corpid));
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        String esData = StringConstant.JSON_DATA + StringConstant.POINT;
        boolQueryBuilder.filter(termsQuery(esData + ContactEnum.CUSTOMER_NAME.getAttr() + keyword, businessIdIn));
        List<PaasFormDataEntityExt> customerLinkContactList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT, boolQueryBuilder, PaasFormDataEntityExt.class, null);
        Map<Long, List<PaasFormDataEntityExt>> contactMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        customerLinkContactList.forEach(contact -> {
            List<PaasFormDataEntityExt> contactEntityList = new ArrayList<>();
            Long linkCustomerId = contact.getData().getLong(ContactEnum.CUSTOMER_NAME.getAttr());
            if (contactMap.containsKey(linkCustomerId)) {
                contactEntityList.addAll(contactMap.get(linkCustomerId));
            }
            contactEntityList.add(contact);
            contactMap.put(linkCustomerId, contactEntityList);
        });
        PaasFormExplainEntity contactExplain = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.CONTACT.getCode(), corpid);
        List<FieldAttrEntity> contactFieldList = JSONArray.parseArray(contactExplain.getExplains(), FieldAttrEntity.class);
        Map<String, FieldAttrEntity> contactExplainMap = ExplainUtil.getExplainMapByList(contactFieldList);

        Integer contactShowPublicPool = 0;
        Integer contactPublicPool = 0;
        // 关联数据
        List<LinkInfoPojo> linkInfoList = new ArrayList<>();
        Set<String> linkDataAttrSet = new HashSet<>();
        for (FieldAttrEntity entity : contactFieldList) {
            if (Objects.equals(entity.getAttr(), ContactEnum.PHONE.getAttr())) {
                contactShowPublicPool = entity.getShowPublicPool();
                contactPublicPool = entity.getPublicPool();
            }
            if (ExplainUtil.isSubForm(entity.getFieldType())) {
                List<? extends FieldAttrEntity> items = entity.getSubForm().getItems();
                for (FieldAttrEntity item : items) {
                    if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), item.getFieldType())) {
                        linkInfoList.add(item.getLinkInfo());
                        linkDataAttrSet.add(entity.getAttr() + StringConstant.POINT + item.getAttr());
                    }
                }

            } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), entity.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), entity.getFieldType())) {
                linkInfoList.add(entity.getLinkInfo());
                linkDataAttrSet.add(entity.getAttr());
            }
        }
        List<Long> formIdList = new ArrayList<>();
        List<Long> workOrderFormIdList = new ArrayList<>();
        for (LinkInfoPojo linkInfoPojo : linkInfoList) {
            if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
            } else {
                formIdList.add(linkInfoPojo.getLinkFormId());
            }
        }
        // 非工单解释
        Map<String, PaasFormExplainEntity> formExplainMap = baseFormDataLinkDataHelp.getExplainMapByFormIdList(formIdList, corpid);
        // 工单解释
        Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = baseFormDataLinkDataHelp.getWorkOrderExplainMapByFormId(workOrderFormIdList, corpid);
        LinkResultDataDTO linkResultDataDTO = new LinkResultDataDTO();
        BeanUtil.copyProperties(formDataListDTO, linkResultDataDTO);

        //获取联系人团队数据
        Set<Long> contactIdList = contactMap.values().stream().flatMap(List::stream).map(PaasFormDataEntityExt::getDataId).collect(Collectors.toSet());
        List<UserTeamEntity> userTeamList = businessUserTeamHelp.getUserTeamList(new ArrayList<>(contactIdList), corpid, XbbRefTypeEnum.CONTACT.getCode(), false);
        Map<Long, List<String>> ownerMap = userTeamList.stream().filter(v -> Objects.equals(v.getIsMain(), Constant.ONE))
                .collect(Collectors.toMap(UserTeamEntity::getDataId, v -> Collections.singletonList(v.getUserId()), (v1, v2) -> {
                    List<String> result = new ArrayList<>(v1);
                    result.addAll(v2);
                    return result;
                }));
        Map<Long, List<String>> coUserMap = userTeamList.stream().filter(v -> Objects.equals(v.getIsMain(), Constant.ZERO))
                .collect(Collectors.toMap(UserTeamEntity::getDataId, v -> Collections.singletonList(v.getUserId()), (v1, v2) -> {
                    List<String> result = new ArrayList<>(v1);
                    result.addAll(v2);
                    return result;
                }));

        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject data = paasFormDataEntityExt.getData();
            Integer isPublic = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_PUBLIC.getAttr(), BasicConstant.ZERO);
            if (Objects.equals(isPublic, BasicConstant.ONE) && Objects.equals(customerShowPublicPool, BasicConstant.ONE) && Objects.equals(customerPublicPool, BasicConstant.ZERO)) {
                // 如果在客户模板电话字段，选了公海池不可见，那么公海客户的电话就不可见
                data.put(CustomerManagementEnum.PHONE.getAttr(), new JSONArray());
            }
            List<PaasFormDataEntityExt> singleCustomerContactList = contactMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>());

            JSONArray contactArray = new JSONArray();
            Map<String, Object> userMap = formDataListDTO.getUserMap();
            Map<String, Object> deptMap = formDataListDTO.getDeptMap();
            List<FieldAttrEntityForImport> fieldAttrEntityForImportList = JSON.parseArray(JSON.toJSONString(contactField.getSubForm().getItems()), FieldAttrEntityForImport.class) ;
            paasFormSubDataModel.findSubEntity(corpid, singleCustomerContactList, IndexTypeEnum.IDX_SAAS_CONTACT_SUB);

            Set<String> linkDataSet = new HashSet<>();
            Set<Object> linkDataIdSet = new HashSet<>();
            Map<String, Set<String>> subFormLinkDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> linkDataIdMap = new HashMap<>();

            // 解析子表单中的关联数据字段
            FormDataListAnalysisDataHelp.getLinkDataField(linkDataAttrSet, FieldAttrConstant.SUB_FORM, linkDataSet, subFormLinkDataMap);

            for (PaasFormDataEntityExt formDataEntityExt : singleCustomerContactList) {
                FormDataListAnalysisDataHelp.getLinkDataSet(formDataEntityExt.getData(), subFormLinkDataMap, linkDataSet, linkDataIdSet, linkDataAttrSet, linkDataIdMap);
            }
            // 获取关联数据字段所需要的数据
            LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
            linkResultDataVO.setExplainMap(contactExplainMap);
            linkResultDataVO.setLinkDataSet(linkDataIdSet);
            linkResultDataVO.setLinkData(linkDataIdMap);
            linkResultDataVO.setExplainList(contactFieldList);
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkData4Field(linkResultDataDTO, linkResultDataVO);

            ExportLinkDataPojo exportLinkDataPojo = new ExportLinkDataPojo(formExplainMap, workOrderFormExplainMap, formDataMap);

            for (PaasFormDataEntityExt contactEntity : singleCustomerContactList) {
                JSONObject contactItemObj = contactEntity.getData();
                Long contactId = contactEntity.getDataId();
                if (Objects.equals(isPublic, BasicConstant.ONE) && Objects.equals(contactShowPublicPool, BasicConstant.ONE) && Objects.equals(contactPublicPool, BasicConstant.ZERO)) {
                    // 如果在联系人模板电话字段，选了公海池不可见，那么公海客户的联系人的电话就不可见
                    contactItemObj.put(ContactEnum.PHONE.getAttr(), new JSONArray());
                }
                //处理联系人的团队数据
                contactItemObj.put(FieldTypeEnum.OWNERID.getAlias(), ownerMap.get(contactId));
                contactItemObj.put(FieldTypeEnum.COUSERID.getAlias(), coUserMap.get(contactId));
                importHelper.formatCommonData4Export(userMap, deptMap, contactEntity, contactItemObj, contactFieldList, null, exportLinkDataPojo, businessType, null);
                importHelper.formatDropDown4Export(fieldAttrEntityForImportList, contactItemObj, null);
                contactArray.add(contactItemObj);
            }
            data.put(CustomerManagementEnum.ADD_CONTACT.getAttr(), contactArray);
        }
    }

    @Override
    public LinkFormItemVO customerCardContactGet(BaseDTO baseDTO) throws XbbException{
        LinkFormItemDTO linkFormItemDTO = new LinkFormItemDTO();
        BeanUtil.copyProperties(baseDTO,linkFormItemDTO);
        linkFormItemDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        String prefix = RedisPrefixConstant.BUZ_CARD_DATA;
        CustomerCardDTO customerCardDTO = new CustomerCardDTO();
        String key =  baseDTO.getCorpid() + ":" + baseDTO.getUserId();
        customerCardDTO = JSONObject.parseObject(paasRedisHelper.getValue(prefix,key),customerCardDTO.getClass());
        linkFormItemDTO.setLinkBusinessType(XbbRefTypeEnum.CONTACT.getCode());
        linkFormItemDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        LinkFormItemVO linkFormItemVO = paasFormExplainService.linkFormList(linkFormItemDTO);
        if (Objects.equals(customerCardDTO.getCustomerType(),1)){
            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
            JSONObject data = new JSONObject();
            data.put(ContactEnum.NAME.getAttr(),customerCardDTO.getName());
            if (!Objects.isNull(customerCardDTO.getPhone()) && !customerCardDTO.getPhone().isEmpty()){
                JSONObject phone = new JSONObject();
                JSONObject text1Obj = new JSONObject();
                text1Obj.put("text",PhoneExtEnum.WORK.getName());
                text1Obj.put("value",PhoneExtEnum.WORK.getCode());
                phone.put("text_1",text1Obj);
                phone.put("text_2",customerCardDTO.getPhone().getString(0));
                data.put(ContactEnum.PHONE.getAttr(),Collections.singletonList(phone));
            }
            data.put(ContactEnum.POSITION.getAttr(),customerCardDTO.getPosition());
//            for (Map.Entry<String,Object> entry : SaasDataInitHelp.initContact().entrySet()){
//                SaasDataInitHelp.antDataSet(data,entry.getKey(),entry.getValue());
//            }
            paasFormDataEntityExt.setData(data);
            linkFormItemVO.setFormDataList(Collections.singletonList(paasFormDataEntityExt));
        }

        return linkFormItemVO;
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList, String contactLabelAttr, Map<String, JSONObject> contactLabelPojoMap) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        formDataAddDTO.setSerialNo("");
        JSONObject dataJson = new JSONObject();
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        Map<String, FieldAttrEntity> explainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (FieldAttrEntityForImport fieldAttr : fieldAttrList) {
            String attr = fieldAttr.getAttr();
            Integer fieldType = fieldAttr.getFieldType();
            String attrName = fieldAttr.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttr, dataJson);
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttr.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttr, cellValue);
                    if (Objects.equals(fieldAttr.getAttr(), CustomerManagementEnum.CUSTOMER_STAGE.getAttr())) {
                        String customerStage = dataJson.getString(attr);
                        CustomerStageEntity customerStageEntity = null;
                        if (StringUtil.isNotEmpty(customerStage)) {
                            customerStageEntity = customerStageModel.getByCode(importFormDataDTO.getCorpid(), importFormDataDTO.getFormId(), customerStage);
                        }
                        if (Objects.nonNull(customerStageEntity) && Objects.equals(customerStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
                            // 流失原因必填
                            List<ItemPoJo> dictionaryList4Saas = dataDictionaryModel.getDictionaryList4Saas(DictionaryEnum.CUSTOMER_STAGE_WASTAGE, importFormDataDTO.getCorpid(), importFormDataDTO.getFormId());
                            if (!dictionaryList4Saas.isEmpty()) {
                                dataJson.put(CustomerManagementEnum.WASTAGE.getAttr(), dictionaryList4Saas.get(0).getValue());
                            }
                        }
                    }
                } else {
                    if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                        formDataAddDTO.setSerialNo(cellValue.toString());
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                        importHelper.formatLinkData(cellValue, fieldAttr, dataJson);
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                        importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttr, dataJson);
                    } else {
                        dataJson.put(attr, cellValue);
                    }
                }
            }
            if (Objects.equals(attr, CustomerManagementEnum.ADD_CONTACT.getAttr())) {
                if (Objects.nonNull(fieldAttr.getSubForm()) && Objects.nonNull(fieldAttr.getSubForm().getItems())) {
                    explainMap = ExplainUtil.getExplainMapByList(fieldAttr.getSubForm().getItems());
                }
            }
        }
        JSONArray contactArr = dataJson.getJSONArray(CustomerManagementEnum.ADD_CONTACT.getAttr());
        if (Objects.nonNull(contactArr) && !contactArr.isEmpty()) {
            for (int i = 0; i < contactArr.size(); i++) {
                JSONObject contactObj = contactArr.getJSONObject(i).getJSONObject(StringConstant.JSON_DATA);
                if (Objects.nonNull(contactObj.get(FieldTypeEnum.DEPARTMENTID.getAlias()))) {
                    Long departmentId = departmentService.verifyDepartment(importFormDataDTO, explainMap, contactObj);
                    contactArr.getJSONObject(i).put(FieldTypeEnum.DEPARTMENTID.getAlias(), departmentId);
                    contactObj.put(FieldTypeEnum.DEPARTMENTID.getAlias(), new ReturnUserAndDepartmentPojo(departmentId));
                }

                // 标签处理
                if (StringUtil.isNotEmpty(contactLabelAttr)){
                    if (Objects.nonNull(contactObj.get(contactLabelAttr))){
                        String[] split = contactObj.getString(contactLabelAttr).split(",");
                        Set<String> labelIdName = new HashSet(Arrays.asList(split));
                        JSONArray jsonArray = new JSONArray();
                        for (String aLong : labelIdName) {
                            if (Objects.nonNull(contactLabelPojoMap.get(aLong))) {
                                jsonArray.add(contactLabelPojoMap.get(aLong));
                            }
                        }
                        contactObj.put(contactLabelAttr, jsonArray);
                    }
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    @Override
    public XbbAggregatedPage<PaasFormDataEntityExt> getDuplicateCustomer(CustomerCheckRepeatDTO customerCheckRepeatDTO) throws XbbException {
        CheckRepeatRuleEnum checkRepeatRuleEnum = CheckRepeatRuleEnum.getByCode(customerCheckRepeatDTO.getRule());
        if (Objects.isNull(checkRepeatRuleEnum)) {
            // 默认按名字查重
            checkRepeatRuleEnum = CheckRepeatRuleEnum.NAME;
        }
        String corpid = customerCheckRepeatDTO.getCorpid();
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid ));
        boolQueryBuilder.filter(termsQuery("del",Arrays.asList(DelEnum.NORMAL.getDel(),DelEnum.DELETE.getDel(),DelEnum.APPROVE_STATUS.getDel())));
        if (customerCheckRepeatDTO.getIsOpenWorkflow() != null && customerCheckRepeatDTO.getIsOpenWorkflow()) {
            // 如果开启了工作流，审批中数据会进入主表，查重的时候可以直接从主表查到
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.FLOW_STATUS.getAlias(), Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType(), FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
        } else {
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.FLOW_STATUS.getAlias(), Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        }
        switch (checkRepeatRuleEnum){
            case NAME:
                boolQueryBuilder.should(termQuery("data." + CustomerManagementEnum.NAME.getAttr() + ".keyword",customerCheckRepeatDTO.getNameLike()).boost(2));
                boolQueryBuilder.should(matchPhraseQuery("data." + CustomerManagementEnum.NAME.getAttr(),customerCheckRepeatDTO.getNameLike()));
                break;
            case PHONE:
                boolQueryBuilder.should(termQuery("data." + CustomerManagementEnum.PHONE.getAttr() + ".text_2" + ".keyword",customerCheckRepeatDTO.getNameLike()).boost(2));
                boolQueryBuilder.should(matchPhraseQuery("data." + CustomerManagementEnum.PHONE.getAttr() + ".text_2",customerCheckRepeatDTO.getNameLike()));
                break;
            default:
                break;
        }
        boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
        Integer page = 1;
        Integer pageSize = 10;
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, (page - 1), pageSize);
        IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, customerIndex.getType()));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(customerIndex.getIndex());
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        return esEntities;
    }

    @Override
    public void formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        customerExplainHandle.newHandleExplain(formatExplainDTO);
    }

    @Override
    public void updateBatchByBusinessRule(OperationDTO operationDTO) throws XbbException {
        try {
            String corpid = operationDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = operationDTO.getFormDataList();
            List<UpdateDataEntity> updateList = operationDTO.getUpdateList();
            if(!updateList.isEmpty()){
                businessRuleUserPermissionHelp.validateFieldCanEdit(operationDTO, updateList, formDataList);
                customerModel.updateBatch(updateList, corpid);
                if(CollectionsUtil.isNotEmpty(updateList)){
                    //评分更新
                    scoreCalculateService.asyncUpdateBatchDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,updateList.stream().map(item->item.getId()).collect(Collectors.toList()));
                }
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(operationDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        }catch (Exception e){
            LOG.error("customerService.updateBatchByBusinessRule 根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 更新时回滚
     * @param idIn
     * @param corpid
     * @throws XbbException
     */
    private void updateRollback(List<Long> idIn, String corpid) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("idIn", idIn);
        if (Objects.isNull(idIn) || idIn.isEmpty()) {
            return;
        }
        param.put(StringConstant.CORPID, corpid);
        List<CustomerEntityExt> customerList = customerModel.findEntitysWithoutSub(param);
        if (Objects.nonNull(customerList)) {
            IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

            for (CustomerEntityExt item : customerList) {
                PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                BeanUtil.copyProperties(item, paasFormDataEntity);
                proEsHelper.reductionEsInUpdate(paasFormDataEntity, item.getId(), corpid, customerIndex);
            }
        }
    }

    @Override
    public String getCutomerNameStr(List<Long> lackCustomerIdList, String corpid) throws XbbException {
        if (lackCustomerIdList.isEmpty()){
            return "";
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),lackCustomerIdList));
        IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());


        List<PaasFormDataEntity> customerList = esHelper.findByScroll(indexTypeEnum, boolQueryBuilder,PaasFormDataEntity.class,Collections.singletonList(CustomerManagementEnum.getAttrConnectData(CustomerManagementEnum.NAME)));
        StringBuilder stringBuilder = new StringBuilder();
        for (PaasFormDataEntity entity : customerList){
            StringUtil.stringBuilderAppendSuffix(stringBuilder,",",entity.getData().getString(CustomerManagementEnum.NAME.getAttr()));
        }
        return stringBuilder.toString();
    }

    @Override
    public void afterSaveForImport(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        String corpid = saasFormSaveDTO.getCorpid();
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONObject oldData = saasFormSaveDTO.getOldData();
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = newPaasFormDataEntity.getId();
        Long formId = newPaasFormDataEntity.getFormId();
        String stageCode = FastJsonHelper.getStringOrDefaultFromFormData(newData, CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), "");
        Integer reasonId = FastJsonHelper.getIntegerOrDefaultFromFormData(newData, CustomerManagementEnum.WASTAGE.getAttr(), BasicConstant.ZERO);
        String wastageMemo = FastJsonHelper.getStringOrDefaultFromFormData(newData, CustomerManagementEnum.WASTAGE_MEMO.getAttr(), "");
        if (Objects.isNull(saasFormSaveDTO.getOwnerId()) || (Objects.nonNull(saasFormSaveDTO.getOwnerId()) && saasFormSaveDTO.getOwnerId().isEmpty())) {
            saasFormSaveDTO.setSubBusinessType(XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode());
        } else {
            SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo();

            AfterSavePojo afterSavePojo = teamDataHelp.saveUserTeam(saasNeedRedundantAttrPoJo, dataId, newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), false);
            // 因为公海池规则报错导致当前数据没有团队添加成功，需要把数据退回公海池
            if (!afterSavePojo.getHaveTeam()) {
                ListBatchDTO listBatchDTO = new ListBatchDTO();
                BeanUtil.copyProperties(saasFormSaveDTO, listBatchDTO);
                listBatchDTO.setDataIdList(Collections.singletonList(dataId));
                listBatchDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                listBatchDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                listBatchDTO.setFormId(newPaasFormDataEntity.getFormId());
                listBatchService.backCustomer(listBatchDTO);
            }
        }
            // 新建的时候阶段不为空或者编辑时阶段不一致才需要更改阶段
            try {
                JudgeStageChangedPojo judgeStageChangedPojo = stageLogHelp.judgeStageChanged(corpid, formId, dataId, stageCode, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                if (judgeStageChangedPojo.getIsStageChanged()) {
                    StageLogSavePojo stageLogSavePojo = new StageLogSavePojo(corpid, formId, dataId, reasonId, wastageMemo, judgeStageChangedPojo);
                    stageLogHelp.saveStageLog(stageLogSavePojo, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                }

                DynamicStrategy dynamicStrategy = dynamicStrategyFactory.getDynamicStrategy(ProjectLogEnum.CUSTOMER_CREATE.getSubType());
                transactionHelp.afterCommitOrCommitNow(p -> {
                    dynamicStrategy.save(DynamicSaveDTO.initDynamicSaveDTO(dataId, formId, saasFormSaveDTO, userModel.getByKeyIngoreDel(newPaasFormDataEntity.getCreatorId(), corpid), judgeStageChangedPojo));
                });
            } catch (Exception e) {
                LOG.error("导入数据客户阶段变更", e);
            }
    }

    @Override
    public void dataConsistencyUpdateParentCustomer(String corpid, Long dataId, String name) {
        try{
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()))
                    .filter(termQuery(CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.PARENT), dataId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(indexTypeEnum, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<CustomerEntityExt> customerEntityExts = customerModel.findEntitys(param);

            if (Objects.nonNull(customerEntityExts) && !customerEntityExts.isEmpty()){
                List<CustomerUpdateDTO> customerUpdateDTOS = new ArrayList<>();
                for (CustomerEntityExt entityExt : customerEntityExts) {
                    CustomerUpdateDTO customerUpdateDTO = new CustomerUpdateDTO();
                    customerUpdateDTO.setId(entityExt.getId());
                    JSONObject data = new JSONObject();
                    data.put(CustomerManagementEnum.PARENT_HIDE.getAttr(), name);
                    customerUpdateDTO.setData(data);
                    customerUpdateDTOS.add(customerUpdateDTO);
                }
                CustomerUpdateBatchDTO customerUpdateBatchDTO = new CustomerUpdateBatchDTO();
                customerUpdateBatchDTO.setCorpid(corpid);
                customerUpdateBatchDTO.setCustomerList(customerUpdateDTOS);
                customerUpdateBatch(customerUpdateBatchDTO);
            }
        } catch (Exception e){
            LOG.error("CustomerServiceImpl.dataConsistencyUpdateParentCustomer 出错，corpid=" + corpid + "  customerId=" + dataId + " customerName=" + name, e);
        }
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        CustomerUpdateBatchDTO customerUpdateBatchDTO = new CustomerUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, customerUpdateBatchDTO);
        List<CustomerUpdateDTO> customerList = new ArrayList<>();
        addBatchList.forEach(item -> {
            CustomerUpdateDTO contractUpdateDTO = new CustomerUpdateDTO();
            contractUpdateDTO.setData(item.getData());
            contractUpdateDTO.setId(item.getId());
            customerList.add(contractUpdateDTO);
        });
        customerUpdateBatchDTO.setCustomerList(customerList);
        customerUpdateBatch(customerUpdateBatchDTO);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseVO customerMerge(CustomerMergeDTO customerMergeDTO) throws XbbException {
        // 副客户关联联系人id
        List<Long> contactIdList = new ArrayList<>();
        // 报价单id
        List<Long> quotationList = new ArrayList<>();
        // 机会id
        List<Long> opportunityList = new ArrayList<>();
        // 跟进记录
        List<Long> customerCommunicateList = new ArrayList<>();
        String corpid = customerMergeDTO.getCorpid();
        Long delId = customerMergeDTO.getDelId();
        Long updateId = customerMergeDTO.getUpdateId();
        Long formId = customerMergeDTO.getFormId();
        // 日志记录
        StringBuilder contactStr = new StringBuilder();
        StringBuilder quotationStr = new StringBuilder();
        StringBuilder opportunityStr = new StringBuilder();
        StringBuilder customerCommunicateStr = new StringBuilder();
        VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO();
        BeanUtil.copyProperties(customerMergeDTO, verifyUpdatePermissionDTO);
        verifyUpdatePermissionDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        ProPermissionHelp.verifyEditPermission(verifyUpdatePermissionDTO);
        List<CustomerEntityExt> mergeCustomer = customerModel.getByKeys(Arrays.asList(delId, updateId), corpid);
        if (CollectionsUtil.isEmpty(mergeCustomer) || mergeCustomer.size() != BasicConstant.TWO) {
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120015, SystemLabelErrorCodeEnum.API_ERROR_1120015.getMsg());
        }
        CustomerEntityExt sourceCustomer = new CustomerEntityExt();
        ContactUpdateBatchDTO sourceContactUpdateBatchDTO = new ContactUpdateBatchDTO();
        OpportunityUpdateBatchDTO sourceOpportunityUpdateBatchDTO = new OpportunityUpdateBatchDTO();
        QuotationUpdateBatchDTO sourceQuotationUpdateBatchDTO = new QuotationUpdateBatchDTO();

        // 1. 判断用户是否有两条数据的编辑权限
        PaasFormExplainEntity explainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        String explains = explainEntity.getExplains();
        List<FieldAttrEntity> explainList = JSON.parseArray(explains, FieldAttrEntity.class);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);

        String name = null;
        // // 3. 更新主客户数据
        List<String> updateAttr = customerMergeDTO.getUpdateAttr();
        CustomerEntityExt updateEntity = new CustomerEntityExt();
        CustomerEntityExt  delEntity = new CustomerEntityExt();
        JSONObject delData = new JSONObject();
        for (CustomerEntityExt customerEntityExt : mergeCustomer) {
            if (Objects.equals(customerEntityExt.getId(), delId)) {
                delEntity = customerEntityExt;
                delData = customerEntityExt.getData();
            } else {
                sourceCustomer = (CustomerEntityExt) CloneUtil.deepClone(customerEntityExt);
                updateEntity = customerEntityExt;
                name = customerEntityExt.getData().getString(CustomerManagementEnum.NAME.getAttr());
            }
        }
        StaticMarketForCustomerMergeEntity staticMarketForCustomerMergeEntity = new StaticMarketForCustomerMergeEntity();
        BeanUtil.copyProperties(customerMergeDTO, staticMarketForCustomerMergeEntity);
        // 判断副客户下是否有合同产生
        linkCustomerContact(delId, corpid, delData);
        // 判断副客户下是否有预收款产生
        linkCustomerPayMent(delId, corpid, delData);
        // 判断副客户下是否有发票产生
        linkCustomerInvoice(delId, corpid, delData);
        // 主副客户有数据在审批中
        // 判断副客户是否有数据在审批中
        judgmentDataInApproval(delId, corpid, delEntity.getData().getString(CustomerManagementEnum.NAME.getAttr()));
        // 判断上級客户不能为自己
        if (updateAttr.contains(CustomerManagementEnum.PARENT.getAttr()) && Objects.nonNull(delData.get(CustomerManagementEnum.PARENT.getAttr()))) {
            Long parentId = delData.getLong(CustomerManagementEnum.PARENT.getAttr());
            if (Objects.equals(parentId, updateId)) {
                throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120020);
            }
        }
        // 3. 更新主客户数据
        // 判断负责人与协同人否有重复值
        JSONArray lastOwnerId = new JSONArray();
        JSONArray lastCouserId = new JSONArray();
        TeamVerifyDTO teamVerifyDTO = null;
        if (!Objects.equals(customerMergeDTO.getBusinessType(), XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode())) {
            // 主客户的负责人必须得查一遍
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(customerMergeDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
            Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(customerMergeDTO, handlerExplainDTO);
            handlerExplainDTO.setExplainList(explainList);
            JSONObject updateOwnerAndCoUser = paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, SaasMarkEnum.SAAS.getCode(), customerMergeDTO.getBusinessType(), customerMergeDTO.getSubBusinessType(), updateEntity, userMap);
            lastOwnerId.addAll(updateOwnerAndCoUser.getJSONArray(FieldTypeEnum.OWNERID.getAlias()));
            lastCouserId.addAll(updateOwnerAndCoUser.getJSONArray(FieldTypeEnum.COUSERID.getAlias()));
            if (updateAttr.contains(FieldTypeEnum.OWNERID.getAlias()) || updateAttr.contains(FieldTypeEnum.COUSERID.getAlias())) {
                // 副客户在有更新条件的情况下查询
                JSONObject delOnerAndCoUser = paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, SaasMarkEnum.SAAS.getCode(), customerMergeDTO.getBusinessType(), customerMergeDTO.getSubBusinessType(), delEntity, userMap);
                if (updateAttr.contains(FieldTypeEnum.OWNERID.getAlias())) {
                    lastOwnerId.clear();
                    lastOwnerId.addAll(delOnerAndCoUser.getJSONArray(FieldTypeEnum.OWNERID.getAlias()));
                }
                if (updateAttr.contains(FieldTypeEnum.COUSERID.getAlias())) {
                    lastCouserId.clear();
                    lastCouserId.addAll(delOnerAndCoUser.getJSONArray(FieldTypeEnum.COUSERID.getAlias()));
                }
            }
            teamVerifyDTO = new TeamVerifyDTO();
            BeanUtil.copyProperties(customerMergeDTO, teamVerifyDTO);
            teamVerifyDTO.setNewAddMainUserList(new HashSet<>(lastOwnerId.toJavaList(String.class)));
            teamVerifyDTO.setNewAddCoUserList(new HashSet<>(lastCouserId.toJavaList(String.class)));
            teamVerifyDTO.setFromDetail(false);
            teamVerifyDTO.setData(sourceCustomer.getData());
            teamVerifyDTO.setDataId(Collections.singletonList(updateId));
        }
        // 用于日志记录
        String updataCustomerName = FastJsonHelper.getStringOrDefaultFromFormData(updateEntity.getData(), CustomerManagementEnum.NAME.getAttr(), "");
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CUSTOMER_MERGE), delData.getString(CustomerManagementEnum.NAME.getAttr()), updataCustomerName);
        //是否包含客户阶段的更新
        Boolean isContainCustomerStage = false;
        List<CustomerStageLogEntity> newCustomerStageLogEntity = null;
        Map<String, Object> searchCustomerStageParam = new HashMap<>(16);
        searchCustomerStageParam.put("corpid", corpid);
        searchCustomerStageParam.put("formId", formId);
        List<String> subFormAttrs = new ArrayList<>();
        // 修改主客户data的值
        for (String item : updateAttr) {
            if (Objects.equals(item, "ownerId") || Objects.equals(item, "coUserId")) {
                continue;
            }
            FieldAttrEntity fieldAttrEntity = explainMap.get(item);
            if (Objects.nonNull(fieldAttrEntity) && Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())) {
                subFormAttrs.add(fieldAttrEntity.getAttr());
                continue;
            }

            if (Objects.equals(item, CustomerManagementEnum.NAME.getAttr())) {
                name = delEntity.getData().getString(CustomerManagementEnum.NAME.getAttr());
            }
            if (Objects.equals(item, CustomerManagementEnum.CLUE_ID.getAttr())) {
                if (Objects.nonNull(updateEntity.getData().get(CustomerManagementEnum.CLUE_ID.getAttr()))) {
                    staticMarketForCustomerMergeEntity.setDelClueIds(JSONArray.parseArray(updateEntity.getData().getString(CustomerManagementEnum.CLUE_ID.getAttr()), Long.class));
                }
                if (Objects.nonNull(delData.get(CustomerManagementEnum.CLUE_ID.getAttr()))) {
                    staticMarketForCustomerMergeEntity.setUpdateClueIds(JSONArray.parseArray(delData.getString(CustomerManagementEnum.CLUE_ID.getAttr()), Long.class));
                }
                updateEntity.getData().put(item, delData.get(item));
                updateEntity.getData().put(CustomerManagementEnum.CLUE_NAME_ID.getAttr(), delData.get(CustomerManagementEnum.CLUE_NAME_ID.getAttr()));
                continue;
            }
            if (Objects.equals(item, CustomerManagementEnum.PARENT.getAttr())) {
                updateEntity.getData().put(item, delData.get(item));
                updateEntity.getData().put(CustomerManagementEnum.PARENT_HIDE.getAttr(), delData.get(CustomerManagementEnum.PARENT_HIDE.getAttr()));
                continue;
            }
            //客户阶段变跟
            if (Objects.equals(item, CustomerManagementEnum.CUSTOMER_STAGE.getAttr())) {
                isContainCustomerStage = true;
                //查询新的客户阶段
                searchCustomerStageParam.put("dataId", delId);
                newCustomerStageLogEntity = customerStageLogModel.findEntitys(searchCustomerStageParam);
                if (CollectionsUtil.isNotEmpty(newCustomerStageLogEntity)) {
                    for (CustomerStageLogEntity customerStage : newCustomerStageLogEntity) {
                        //修改customerId为主客户的，避免下面的阶段查询再遍历一遍
                        customerStage.setDataId(updateId);
                        //客户阶段为"流失"，需要更新"流失原因","流失备注"
                        if (Objects.equals(customerStage.getStageType(), StageTypeEnum.FAIL_STAGE.getType())) {
                            updateEntity.getData().put(CustomerManagementEnum.WASTAGE.getAttr(), delData.get(CustomerManagementEnum.WASTAGE.getAttr()));
                            updateEntity.getData().put(CustomerManagementEnum.WASTAGE_MEMO.getAttr(), delData.get(CustomerManagementEnum.WASTAGE_MEMO.getAttr()));
                        }
                    }
                }
                updateEntity.getData().put(CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), delData.get(CustomerManagementEnum.CUSTOMER_STAGE.getAttr()));
                updateEntity.getData().put(CustomerManagementEnum.STAGE_PROCESS_ID.getAttr(), delData.get(CustomerManagementEnum.STAGE_PROCESS_ID.getAttr()));
                updateEntity.getData().put(CustomerManagementEnum.STAGE_ID.getAttr(), delData.get(CustomerManagementEnum.STAGE_ID.getAttr()));
                updateEntity.getData().put(CustomerManagementEnum.STAGE_RATIO.getAttr(), delData.get(CustomerManagementEnum.STAGE_RATIO.getAttr()));
                continue;
            }
            if (Objects.equals(item, FieldTypeEnum.SERIALNO.getAlias())) {
                updateEntity.setSerialNo(delEntity.getSerialNo());
            } else {
                updateEntity.getData().put(item, delData.get(item));
            }
        }
        if (updateAttr.contains(FieldTypeEnum.OWNERID.getAlias()) || updateAttr.contains(FieldTypeEnum.COUSERID.getAlias())) {
            for (Object o : lastOwnerId) {
                if (lastCouserId.contains(o.toString())) {
                    throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200025, BuinessDefaultErrorCodeEnum.API_ERROR_200025.getMsg());
                }
            }
        }
        if (Objects.nonNull(updateEntity.getData().get(CustomerManagementEnum.CLUE_ID.getAttr()))) {
            staticMarketForCustomerMergeEntity.setDelClueIds(JSONArray.parseArray(updateEntity.getData().getString(CustomerManagementEnum.CLUE_ID.getAttr()), Long.class));
        }
        if (Objects.nonNull(delData.get(CustomerManagementEnum.CLUE_ID.getAttr()))) {
            staticMarketForCustomerMergeEntity.setUpdateClueIds(JSONArray.parseArray(delData.getString(CustomerManagementEnum.CLUE_ID.getAttr()), Long.class));
        }
        try {
            // 合并后的客户保留最早的创建时间和最晚的跟进时间
            if (subFormAttrs.size() > 0) {
                BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
                boolQueryBuilder.filter(termQuery("formId", formId));
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery("dataId", delId));
                boolQueryBuilder.filter(termsQuery("attr.keyword", subFormAttrs));
                boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
                IndexTypeEnum customerSubIndex = indexTypeModel.getCustomerSubIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, customerSubIndex.getType()));
                SearchRequest searchRequest = new SearchRequest(customerSubIndex.getIndex());
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                sourceBuilder.query(boolQueryBuilder);
                searchRequest.source(sourceBuilder);
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, SizeConstant.PAGE_SIZE);
                XbbAggregatedPage<PaasFormSubDataEntity> subData = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormSubDataEntity.class);
                List<PaasFormSubDataEntity> subDataList = subData.getContent();
                JSONObject data = updateEntity.getData();
                Map<String, JSONArray> attr2data = new HashMap<>(subFormAttrs.size());
                subDataList.forEach(item -> {
                    if (subFormAttrs.contains(item.getAttr())) {
                        if (Objects.nonNull(attr2data.get(item.getAttr()))) {
                            JSONArray jsonArray = attr2data.get(item.getAttr());
                            jsonArray.add(item.getData());
                        } else {
                            JSONArray jsonArray = new JSONArray();
                            jsonArray.add(item.getData());
                            attr2data.put(item.getAttr(), jsonArray);
                        }
                    }
                });
                data.putAll(attr2data);
            }
            Long updateTime = delEntity.getData().getLong(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr());
            Long addTime = delEntity.getAddTime();
            Long addTime1 = updateEntity.getAddTime();
            Long updateTime1 = updateEntity.getData().getLong(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr());

            updateEntity.setAddTime(addTime > addTime1 ? addTime1 : addTime);
            updateEntity.getData().put(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), updateTime > updateTime1 ? updateTime : updateTime1);
            // 如果客户阶段修改的话,还得对客户阶段特殊处理
            if (isContainCustomerStage) {
                //删除旧的客户阶段
                searchCustomerStageParam.put("dataId", updateId);
                customerStageLogModel.deleteEntitys(searchCustomerStageParam);
                // 更新现有的客户阶段
                if (CollectionsUtil.isNotEmpty(newCustomerStageLogEntity)) {
                    customerStageLogModel.updateBatch(newCustomerStageLogEntity, corpid);
                }
            }
            // 4. 关联的表单数据迁移
            // 联系人
            ContactUpdateBatchDTO contactUpdateBatchDTO = migrateContact(customerMergeDTO, delId, updateId, corpid, name, contactIdList, contactStr, sourceContactUpdateBatchDTO);
            // 机会
            OpportunityUpdateBatchDTO opportunityUpdateBatchDTO = migrateOpportunity(customerMergeDTO, delId, updateId, corpid, name, opportunityList, opportunityStr, sourceOpportunityUpdateBatchDTO);
            // 报价单
            QuotationUpdateBatchDTO quotationUpdateBatchDTO = migrateQuotation(customerMergeDTO, delId, updateId, corpid, name, quotationList, quotationStr, sourceQuotationUpdateBatchDTO);
            // 跟进记录
            CustomerCommunicateUpdateBatchDTO customerCommunicateUpdateBatchDTO = migrateCustomerCommunicate(customerMergeDTO, delId, updateId, corpid , name, customerCommunicateList, customerCommunicateStr);


            // 联系人更新
            if (CollectionsUtil.isNotEmpty(contactUpdateBatchDTO.getContactList())) {
                contactService.updateBatch(contactUpdateBatchDTO);
            }
            // purchaseInvoiceService.update
            // 机会更新
            if (CollectionsUtil.isNotEmpty(opportunityUpdateBatchDTO.getOpportunityList())) {
                opportunityService.updateBatch(opportunityUpdateBatchDTO);
            }
            // 报价单更新
            if (CollectionsUtil.isNotEmpty(quotationUpdateBatchDTO.getQuotationUpdateDTOList())) {
                quotationService.updateBatch(quotationUpdateBatchDTO);
            }
            // 跟进记录更新
            if (CollectionsUtil.isNotEmpty(customerCommunicateUpdateBatchDTO.getCommunicateUpdateList())) {
                customerCommunicateService.updateBatch(customerCommunicateUpdateBatchDTO);
            }
            // 主客户更新
            customerModel.update(updateEntity);
            // // 修改负责人协同人
            // if (Objects.nonNull(updateMyTeamDTO)) {
            //     saasDetailTabService.updateMyTeam(updateMyTeamDTO);
            // }
            // 这些不涉及到主流程的数据可以异步处理
            asynchronousProcessingData(customerMergeDTO, customerCommunicateList, corpid, delId, updateId, customerCommunicateStr, name);

            // 副客户删除
            CustomerDeleteBatchDTO customerDeleteBatchDTO = new CustomerDeleteBatchDTO();
            customerDeleteBatchDTO.setDataIdList(Arrays.asList(delId));
            BeanUtil.copyProperties(customerMergeDTO, customerDeleteBatchDTO);
            customerDeleteBatchDTO.setIsRemoveCompletely(BasicConstant.ONE);

            // 修改负责人协同人
            if (Objects.nonNull(teamVerifyDTO)) {
                customerMergeTeam(teamVerifyDTO, updateEntity, updateAttr, delId);
                //saasDetailTabService.updateMyTeam(updateMyTeamDTO);
            }
            mergeCustomerDeleteBatch(customerDeleteBatchDTO);
//            dealStaticMarket(staticMarketForCustomerMergeEntity, updateAttr);
//            deleteBatch(customerDeleteBatchDTO);
//            if (updateAttr.contains(CustomerManagementEnum.CLUE_ID.getAttr())){
            marketActivityForStaticHelp.deal2customerMerge(staticMarketForCustomerMergeEntity);
//            }
            // 动态
            try {
                if (Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), customerMergeDTO.getDistributorMark())) {
                    String communicateMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.MERGE_CUSTOMER), customerMergeDTO.getLoginUserName(), delData.getString(CustomerManagementEnum.NAME.getAttr()), updateEntity.getData().getString(CustomerManagementEnum.NAME.getAttr()));
                    CustomerDynamicAddDTO customerDynamicAddDTO =
                            CustomerDynamicAddDTO.initCustomerDynamicAddDTO(corpid, customerMergeDTO.getUserId(), null, communicateMemo, updateEntity.getId(), name, 0L, null, null, ProjectLogEnum.CUSTOMER_STAGE.getSubType());
                    customerDynamicAddDTO.setDistributorMark(DistributorMarkEnum.DISTRIBUTOR.getCode());
                    customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
                }else {
                    CustomerDynamicStrategy customerDynamicStrategy = dynamicStrategyFactory.getCustomerDynamicStrategy(ProjectLogEnum.CUSTOMER_MERGE.getSubType());
                    customerDynamicStrategy.merge(new DynamicMergeDTO(customerMergeDTO, sourceCustomer, delEntity));
                }
            } catch (Exception e) {
                LOG.error("客户合并动态失败", e);
            }

            // 全部删除
            // customerModel.thoroughDeleteBatch(Arrays.asList(delId), corpid, DelEnum.REMOVE_COMPLETELY.getDel());
            // 日志记录
            CustomerMergeLogDTO customerMergeLogDTO = new CustomerMergeLogDTO(sourceCustomer,updateEntity,delEntity,customerMergeDTO);
            customerOperationLogHandle.merge(customerMergeLogDTO);

            //评分更新（客户合并）
            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, corpid, updateEntity.getId(), null);
        } catch (XbbException e) {
            LOG.error("合并负责人执行失败XbbException",e);
            customerModel.update(sourceCustomer);
            // 联系人更新
            if (CollectionsUtil.isNotEmpty(sourceContactUpdateBatchDTO.getContactList())) {
                contactService.updateBatch(sourceContactUpdateBatchDTO);
            }
            // purchaseInvoiceService.update
            // 机会更新
            if (CollectionsUtil.isNotEmpty(sourceOpportunityUpdateBatchDTO.getOpportunityList())) {
                opportunityService.updateBatch(sourceOpportunityUpdateBatchDTO);
            }
            // 报价单更新
            if (CollectionsUtil.isNotEmpty(sourceQuotationUpdateBatchDTO.getQuotationUpdateDTOList())) {
                quotationService.updateBatch(sourceQuotationUpdateBatchDTO);
            }
            // customerCommunicateService.updateRollback(customerCommunicateList, corpid);
            throw e;
        } catch (Exception e) {
            LOG.error("合并负责人执行失败Exception",e);
            customerModel.update(sourceCustomer);
            // 联系人更新
            if (CollectionsUtil.isNotEmpty(sourceContactUpdateBatchDTO.getContactList())) {
                contactService.updateBatch(sourceContactUpdateBatchDTO);
            }
            // 机会更新
            if (CollectionsUtil.isNotEmpty(sourceOpportunityUpdateBatchDTO.getOpportunityList())) {
                opportunityService.updateBatch(sourceOpportunityUpdateBatchDTO);
            }
            // 报价单更新
            if (CollectionsUtil.isNotEmpty(sourceQuotationUpdateBatchDTO.getQuotationUpdateDTOList())) {
                quotationService.updateBatch(sourceQuotationUpdateBatchDTO);
            }
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return new BaseVO();
    }

    /**
     * 合并客户的情况下涉及到团队的一些逻辑
     * （1）共享模式可以直接调用我们现有的底层方法
     * （2）隔离模式需要特殊逻辑处理一下
     *
     * @param teamVerifyDTO
     * @param updateEntity
     * @param updateEntity
     */
    private void customerMergeTeam(TeamVerifyDTO teamVerifyDTO, CustomerEntityExt updateEntity, List<String> updateAttr, Long delId) throws XbbException {
        teamVerifyDTO.setOperateTag(OperateTypeEnum.CUSTOMER_MERGE.getCode());
        boolean formShareTag = userTeamHelp.getFormShareTag(teamVerifyDTO.getCorpid(), teamVerifyDTO.getFormId(), teamVerifyDTO.getBusinessType());
        if (formShareTag) {
            //共享模式
            TeamStrategy teamStrategy = teamDataFactory.getStrategy(teamVerifyDTO.getBusinessType(), teamVerifyDTO.getDistributorMark(), teamVerifyDTO.getSaasMark());
            TeamAfterVerifyDTO teamAfterVerifyDTO = teamStrategy.verify(teamVerifyDTO);
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(updateEntity, paasFormDataEntity);
            teamAfterVerifyDTO.setPaasFormDataEntity(paasFormDataEntity);

            if (CollectionsUtil.isEmpty(teamAfterVerifyDTO.getTeamBatchPojos())) {
                teamDataHelp.businessSave(teamAfterVerifyDTO);
            }

            List<TeamBatchPojo> teamBatchPojos = teamAfterVerifyDTO.getTeamBatchPojos();
            if (CollectionsUtil.isNotEmpty(teamBatchPojos)) {
                throw new XbbException(teamBatchPojos.get(0).getCode(), teamBatchPojos.get(0).getFailMsgReason());
            }
        }else {
            //隔离模式下,选择一个客户的负责人，那么协同人也会是这个客户下的;虽然是隔离模式，但是校验得按照共享模式校验
            if (updateAttr.contains(FieldTypeEnum.OWNERID.getAlias())) {
                TeamStrategy teamStrategy = teamDataFactory.getStrategy(teamVerifyDTO.getBusinessType(), teamVerifyDTO.getDistributorMark(), teamVerifyDTO.getSaasMark());
                TeamAfterVerifyDTO teamAfterVerifyDTO = teamStrategy.verify(teamVerifyDTO);

                if (CollectionsUtil.isEmpty(teamAfterVerifyDTO.getTeamBatchPojos())) {
                    PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                    BeanUtil.copyProperties(updateEntity, paasFormDataEntity);
                    teamAfterVerifyDTO.setPaasFormDataEntity(paasFormDataEntity);
                    teamDataHelp.isolationMergeCustomerSave(teamAfterVerifyDTO, delId);
                }
                List<TeamBatchPojo> teamBatchPojos = teamAfterVerifyDTO.getTeamBatchPojos();
                if (CollectionsUtil.isNotEmpty(teamBatchPojos)) {
                    throw new XbbException(teamBatchPojos.get(0).getCode(), teamBatchPojos.get(0).getFailMsgReason());
                }
            }
        }

    }

    /**
     * 异步处理的数据
     * @param customerMergeDTO
     * @param customerCommunicateList
     * @param corpid
     * @param delId
     * @param updateId
     * @param customerCommunicateStr
     * @param name
     * @throws XbbException
     */
    public void asynchronousProcessingData(CustomerMergeDTO customerMergeDTO, List<Long> customerCommunicateList, String corpid, Long delId, Long updateId, StringBuilder customerCommunicateStr, String name) throws XbbException {

        Runnable runnable = () -> {
            try {
                ConsistencySyncRabbitMqDTO consistencySyncRabbitMqDTO = new ConsistencySyncRabbitMqDTO();
                BeanUtil.copyProperties(customerMergeDTO, consistencySyncRabbitMqDTO);
                consistencySyncRabbitMqDTO.setCorpid(corpid);
                consistencySyncRabbitMqDTO.setName(name);
                consistencySyncRabbitMqDTO.setDataId(updateId);
                consistencySyncService.syncCustomer(consistencySyncRabbitMqDTO);
                // 跟进记录
                // CustomerCommunicateUpdateBatchDTO customerCommunicateUpdateBatchDTO = migrateCustomerCommunicate(customerMergeDTO, delId, updateId, corpid , name, customerCommunicateList, customerCommunicateStr);

                // 文件柜迁移
                List<CabinetFileEntity> cabinetFileEntities = migrateCabinetFile(customerMergeDTO, delId, updateId, corpid, name);
                // // 跟进记录更新
                // if (CollectionsUtil.isNotEmpty(customerCommunicateUpdateBatchDTO.getCommunicateUpdateList())) {
                //     customerCommunicateService.updateBatch(customerCommunicateUpdateBatchDTO);
                // }

                // 文件柜更新
                if (CollectionsUtil.isNotEmpty(cabinetFileEntities)) {
                    cabinetFileModel.updateBatch(cabinetFileEntities, corpid);
                }
                // 迁移审批中的数据
                // 联系人
                List<PaasProcessDataEntity> paasProcessDataEntities = new ArrayList<>();
                List<PaasProcessDataEntity> contactData = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.CONTACT.getCode(), ContactEnum.CUSTOMER_NAME.getAttr(), Arrays.asList(delId), corpid, null);
                for (PaasProcessDataEntity item : contactData) {
                    JSONObject jsonObject = JSON.parseObject(item.getData());
                    jsonObject.put(ContactEnum.CUSTOMER_NAME.getAttr(), updateId);
                    jsonObject.put(ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), name);
                    item.setData(jsonObject.toJSONString());
                    paasProcessDataEntities.add(item);
                }
                // 销售机会
                List<PaasProcessDataEntity> opportunityData = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(), SalesOpportunityEnum.CUSTOMER_NAME.getAttr(), Arrays.asList(delId), corpid, null);
                for (PaasProcessDataEntity opportunityDatum : opportunityData) {
                    JSONObject jsonObject = JSON.parseObject(opportunityDatum.getData());
                    jsonObject.put(SalesOpportunityEnum.CUSTOMER_NAME.getAttr(), updateId);
                    jsonObject.put(SalesOpportunityEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), name);
                    opportunityDatum.setData(jsonObject.toJSONString());
                    paasProcessDataEntities.add(opportunityDatum);
                }
                // 报价单
                List<PaasProcessDataEntity> quotationData = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.QUOTATION.getCode(), QuotationEnum.CUSTOMER_ID.getAttr(), Arrays.asList(delId), corpid, null);
                for (PaasProcessDataEntity opportunityDatum : quotationData) {
                    JSONObject jsonObject = JSON.parseObject(opportunityDatum.getData());
                    jsonObject.put(QuotationEnum.CUSTOMER_NAME.getAttr(), updateId);
                    jsonObject.put(QuotationEnum.CUSTOMER_NAME.getAttr(), name);
                    opportunityDatum.setData(jsonObject.toJSONString());
                    paasProcessDataEntities.add(opportunityDatum);
                }
                // 合同(有被审批拒绝的合同)
                List<PaasProcessDataEntity> contractData = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.CONTRACT.getCode(), ContractEnum.LINK_CUSTOMER.getAttr(), Arrays.asList(delId), corpid, null);
                for (PaasProcessDataEntity contract : contractData) {
                    JSONObject jsonObject = JSON.parseObject(contract.getData());
                    jsonObject.put(ContractEnum.LINK_CUSTOMER.getAttr(), updateId);
                    jsonObject.put(ContractEnum.LINK_CUSTOMER_HIDE.getAttr(), name);
                    contract.setData(jsonObject.toJSONString());
                    paasProcessDataEntities.add(contract);
                }

                if (CollectionsUtil.isNotEmpty(paasProcessDataEntities)) {
                    paasProcessDataModel.updateBatch(paasProcessDataEntities, corpid);
                }

                //合并个人标签
                personLabelService.mergePersonLabel(customerMergeDTO);
            } catch (XbbException e) {
                LOG.info("客户合并--------非主业务迁移失败");
            }
        };
        threadPoolBeanConfig.customerMerge().execute(runnable);
    }

    /**
     * 副客户下有关联发票,不允许合并
     * @param delId
     * @param corpid
     * @param delData
     * @throws XbbException
     */
    private void linkCustomerInvoice(Long delId, String corpid, JSONObject delData) throws XbbException {
        BoolQueryBuilder booleanQuery = boolQuery();
        String customerAttr = InvoiceEnum.CUSTOMER_NAME.getAttr();
        String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
        booleanQuery.filter(termsQuery(linkCustomer, Arrays.asList(delId)));
        booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        // List<String> fieldList = new ArrayList<>();
        // fieldList.add(linkCustomer);
        List<PaasFormDataEntityExt> linkCustomerList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INVOICE, booleanQuery, PaasFormDataEntityExt.class, null);
        if (CollectionsUtil.isNotEmpty(linkCustomerList)) {
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120010, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120010.getMsg(), delData.getString(CustomerManagementEnum.NAME.getAttr()), XbbRefTypeEnum.INVOICE.getName()));
        }

        // 销项发票
        List<PaasProcessDataEntity> invoiceInApproval = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.INVOICE.getCode(), InvoiceEnum.CUSTOMER_NAME.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(invoiceInApproval)){
            // 副客户有销项发票在审批中,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), delData.getString(CustomerManagementEnum.NAME.getAttr()), XbbRefTypeEnum.INVOICE.getName()));
        }
    }

    /**
     * 副客户下有预收款不支持合并
     * @param delId
     * @param corpid
     * @param delData
     * @throws XbbException
     */
    private void linkCustomerPayMent(Long delId, String corpid, JSONObject delData) throws XbbException {
        BoolQueryBuilder payMBQuery = boolQuery();
        payMBQuery.filter(termsQuery(PaymentBalanceEnum.CUSTOMER_ID.getAttr(), Arrays.asList(delId)));
        payMBQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        payMBQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));

        List<PaymentBalanceEntity> payMentBalanceList = esHelper.findByScroll(IndexTypeEnum.IDX_PAYMENT_BALANCE, payMBQuery, PaymentBalanceEntity.class, Arrays.asList("id",PaymentBalanceEnum.CUSTOMER_ID.getAttr(),PaymentBalanceEnum.ADVANCE_PAYMENT_BALANCE.getAttr()));
        if(CollectionsUtil.isNotEmpty(payMentBalanceList)){
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120010, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120010.getMsg(), delData.getString(CustomerManagementEnum.NAME.getAttr()), XbbRefTypeEnum.PREPAYMENT_BALANCE.getName()));
        }

        // 回款单
        List<PaasProcessDataEntity> paymentInApproval = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(), PaymentBalanceEnum.CUSTOMER_ID.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(paymentInApproval)){
            // 副客户有销售机会在审批中,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), delData.getString(CustomerManagementEnum.NAME.getAttr()), XbbRefTypeEnum.PAYMENT.getName()));
        }
    }


    private List<CabinetFileEntity> migrateCabinetFile(CustomerMergeDTO customerMergeDTO, Long dataId, Long updateId, String corpid, String name) throws XbbException {

        List<CabinetFileEntity> entitys = null;
        try {
            Integer businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("corpid", corpid);
            params.put("del", 0);
            params.put("orderByStr", "add_time desc");
            params.put("dataId", dataId);
            params.put("businessType", businessType);
            entitys = cabinetFileModel.findEntitys(params);
            entitys.forEach(item-> item.setDataId(updateId));
        } catch (Exception e) {
            LOG.error("迁移文件柜失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        return entitys;
    }

    private CustomerCommunicateUpdateBatchDTO migrateCustomerCommunicate(CustomerMergeDTO customerMergeDTO, Long delId, Long updateId, String corpid, String name, List<Long> idList, StringBuilder nameStr) throws XbbException {
        CustomerCommunicateUpdateBatchDTO updateBatchDTO = new CustomerCommunicateUpdateBatchDTO();
        BeanUtil.copyProperties(customerMergeDTO, updateBatchDTO);
        try {
            BoolQueryBuilder booleanQuery = boolQuery();
            String customerAttr = CustomerCommunicateEnum.CUSTOMER_NAME.getAttr();
            String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
            booleanQuery.filter(termsQuery(linkCustomer, Arrays.asList(delId)));
            booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            booleanQuery.filter(termQuery("logType",0));
            // List<String> fieldList = new ArrayList<>();
            // fieldList.add(linkCustomer);
            List<PaasFormDataEntityExt> linkCustomerList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE, booleanQuery, PaasFormDataEntityExt.class, null);
            if (CollectionsUtil.isNotEmpty(linkCustomerList)) {
                List<CustomerCommunicateUpdateDTO> updateList = new ArrayList<>();
                for (PaasFormDataEntityExt item : linkCustomerList) {
                    nameStr.append(item.getData().getString("id")).append(",");
                    CustomerCommunicateUpdateDTO updateDTO = new CustomerCommunicateUpdateDTO();
                    BeanUtil.copyProperties(item, updateDTO);
                    JSONObject data = item.getData();
                    if (Objects.nonNull(name)){
                        data.put(CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(),name);
                    }
                    data.put(customerAttr, updateId);
                    updateDTO.setData(data);
                    updateList.add(updateDTO);
                    idList.add(item.getId());
                }
                updateBatchDTO.setCommunicateUpdateList(updateList);
            }
        } catch (XbbException e) {
            LOG.error("客户合并 跟进记录迁移失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return updateBatchDTO;
    }

    /**
     * 修改报价单关联的客户id
     * @param delId
     * @param updateId
     * @param corpid
     * @return
     */
    private QuotationUpdateBatchDTO migrateQuotation(CustomerMergeDTO customerMergeDTO, Long delId, Long updateId, String corpid, String name, List<Long> idList, StringBuilder nameStr,  QuotationUpdateBatchDTO sourceQuotationUpdateBatchDTO) throws XbbException {
        QuotationUpdateBatchDTO updateBatchDTO = new QuotationUpdateBatchDTO();
        BeanUtil.copyProperties(customerMergeDTO, updateBatchDTO);
        BeanUtil.copyProperties(customerMergeDTO, sourceQuotationUpdateBatchDTO);
        try {
            BoolQueryBuilder booleanQuery = boolQuery();
            String customerAttr = QuotationEnum.CUSTOMER_ID.getAttr();
            String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
            booleanQuery.filter(termQuery(linkCustomer, delId));
            booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<QuotationEntityExt> quotationList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_QUOTATION, booleanQuery, QuotationEntityExt.class, null);
            // quotationEntityExts = (List<QuotationEntityExt>)CloneUtil.deepClone(quotationList);
            if (CollectionsUtil.isNotEmpty(quotationList)) {
                List<QuotationUpdateDTO> updateList = new ArrayList<>();
                List<QuotationUpdateDTO> sourceList = new ArrayList<>();
                for (PaasFormDataEntityExt item : quotationList) {
                    nameStr.append(item.getData().getString(QuotationEnum.NAME.getAttr())).append(",");
                    QuotationUpdateDTO updateDTO = new QuotationUpdateDTO();
                    QuotationUpdateDTO sourceDTO = new QuotationUpdateDTO();
                    BeanUtil.copyProperties(item, updateDTO);
                    BeanUtil.copyProperties(item, sourceDTO);
                    JSONObject data = item.getData();
                    if (Objects.nonNull(name)){
                        data.put(QuotationEnum.CUSTOMER_NAME.getAttr(), name);
                    }
                    data.put(customerAttr, updateId);
                    updateDTO.setData(data);
                    updateList.add(updateDTO);
                    sourceList.add(sourceDTO);
                    idList.add(item.getId());
                }
                updateBatchDTO.setQuotationUpdateDTOList(updateList);
                sourceQuotationUpdateBatchDTO.setQuotationUpdateDTOList(sourceList);
            }
        } catch (XbbException e) {
            LOG.error("客户合并 销项发票迁移失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return updateBatchDTO;
    }

    /**
     * 修改销售机回关联的客户id
     * @param delId
     * @param updateId
     * @param corpid
     * @return
     */
    private OpportunityUpdateBatchDTO migrateOpportunity(CustomerMergeDTO customerMergeDTO, Long delId, Long updateId, String corpid, String name, List<Long> idList, StringBuilder nameStr,OpportunityUpdateBatchDTO sourceOpportunityUpdateBatchDTO) throws XbbException {
        OpportunityUpdateBatchDTO updateBatchDTO = new OpportunityUpdateBatchDTO();
        BeanUtil.copyProperties(customerMergeDTO, updateBatchDTO);
        BeanUtil.copyProperties(customerMergeDTO, sourceOpportunityUpdateBatchDTO);
        try {
            BoolQueryBuilder booleanQuery = boolQuery();
            String customerAttr = SalesOpportunityEnum.CUSTOMER_NAME.getAttr();
            String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
            booleanQuery.filter(termQuery(linkCustomer, delId));
            booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<OpportunityEntityExt> opportunityEntityExts = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OPPORTUNITY, booleanQuery, OpportunityEntityExt.class, null);
            // copyOpportunity = (List<OpportunityEntityExt>)CloneUtil.deepClone(opportunityEntityExts);
            if (CollectionsUtil.isNotEmpty(opportunityEntityExts)) {
                List<OpportunityUpdateDTO> updateList = new ArrayList<>();
                List<OpportunityUpdateDTO> sourceList = new ArrayList<>();
                for (PaasFormDataEntityExt item : opportunityEntityExts) {
                    nameStr.append(SalesOpportunityEnum.SERIAL_NO.getAttr()).append(",");
                    OpportunityUpdateDTO updateDTO = new OpportunityUpdateDTO();
                    OpportunityUpdateDTO sourceDTO = new OpportunityUpdateDTO();
                    BeanUtil.copyProperties(item, updateDTO);
                    BeanUtil.copyProperties(item, sourceDTO);
                    JSONObject data = item.getData();
                    if (Objects.nonNull(name)){
                        data.put(SalesOpportunityEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), name);
                    }
                    data.put(customerAttr, updateId);
                    updateDTO.setData(data);
                    updateList.add(updateDTO);
                    sourceList.add(sourceDTO);
                    idList.add(item.getId());
                }
                updateBatchDTO.setOpportunityList(updateList);
                sourceOpportunityUpdateBatchDTO.setOpportunityList(sourceList);
            }
        } catch (XbbException e) {
            LOG.error("客户合并 销项发票迁移失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return updateBatchDTO;
    }

    /**
     * 修改联系人关联的客户id
     * @param delId
     * @param updateId
     * @param corpid
     * @return
     * @throws XbbException
     */
    private ContactUpdateBatchDTO migrateContact(CustomerMergeDTO customerMergeDTO, Long delId, Long updateId, String corpid, String name, List<Long> idList ,StringBuilder nameStr, ContactUpdateBatchDTO sourceContactUpdateBatchDTO) throws XbbException {
        ContactUpdateBatchDTO contactUpdateBatchDTO = new ContactUpdateBatchDTO();
        BeanUtil.copyProperties(customerMergeDTO, contactUpdateBatchDTO);
        BeanUtil.copyProperties(customerMergeDTO, sourceContactUpdateBatchDTO);
        try {
            BoolQueryBuilder booleanQuery = boolQuery();
            String customerAttr = ContactEnum.CUSTOMER_NAME.getAttr();
            String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
            booleanQuery.filter(termQuery(linkCustomer, delId));
            booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<ContactEntityExt> contactList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT, booleanQuery, ContactEntityExt.class, null);
            // 主副联系人修改
            /*Boolean flag = false;
            for (PaasFormDataEntityExt paasFormDataEntityExt : contactList) {
                if (Objects.equals(paasFormDataEntityExt.getData().getLong(ContactEnum.CUSTOMER_NAME.getAttr()), updateId)) {
                    flag = true;
                    break;
                }
            }*/
            if (CollectionsUtil.isNotEmpty(contactList)) {
                List<ContactUpdateDTO> updateList = new ArrayList<>();
                List<ContactUpdateDTO> sourceDataList = new ArrayList<>();
                for (PaasFormDataEntityExt item : contactList) {
                    if (Objects.equals(item.getData().getLong(ContactEnum.CUSTOMER_NAME.getAttr()), updateId)){
                        continue;
                    }
                    if (Objects.equals(item.getData().getInteger(ContactEnum.IS_MAIN.getAttr()), BasicConstant.ONE)){
                        item.getData().put(ContactEnum.IS_MAIN.getAttr(), BasicConstant.ZERO);
                    }
                    nameStr.append(item.getData().getString(ContactEnum.NAME.getAttr())).append(",");
                    ContactUpdateDTO updateDTO = new ContactUpdateDTO();
                    ContactUpdateDTO sourceDTO = new ContactUpdateDTO();
                    BeanUtil.copyProperties(item, sourceDTO);
                    BeanUtil.copyProperties(item, updateDTO);
                    JSONObject data = item.getData();
                    if (Objects.nonNull(name)) {
                        data.put(ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), name);
                    }
                    data.put(ContactEnum.CUSTOMER_NAME.getAttr(), updateId);
                    sourceDataList.add(sourceDTO);
                    updateDTO.setData(data);
                    updateList.add(updateDTO);
                    idList.add(item.getId());
                }
                sourceContactUpdateBatchDTO.setContactList(sourceDataList);
                contactUpdateBatchDTO.setContactList(updateList);
            }
        } catch (XbbException e) {
            LOG.error("客户合并 联系人迁移失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return contactUpdateBatchDTO;

    }


    /**
     * 判断副客户是否有关联数据在审批中
     * @param delId
     * @param corpid
     * @throws XbbException
     */
    private void judgmentDataInApproval(Long delId, String corpid, String name) throws XbbException {
        // 联系人
        List<PaasProcessDataEntity> contactInApproval = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.CONTACT.getCode(), ContactEnum.CUSTOMER_NAME.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(contactInApproval)){
            // 副客户下有联系人在审批中无法删除,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), name, XbbRefTypeEnum.CONTACT.getName()));
        }
        // 销售机会
        List<PaasProcessDataEntity> opportunityInApproval = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(), SalesOpportunityEnum.CUSTOMER_NAME.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(opportunityInApproval)){
            // 副客户有销售机会在审批中,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), name, XbbRefTypeEnum.SALES_OPPORTUNITY.getName()));
        }
        // 报价单
        List<PaasProcessDataEntity> quotationInApproval = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.QUOTATION.getCode(), QuotationEnum.CUSTOMER_NAME.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(quotationInApproval)){
            // 副客户有销售机会在审批中,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), name, XbbRefTypeEnum.QUOTATION.getName()));
        }
        // 工单
        List<PaasProcessDataEntity> workOrderInApproval = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.WORK_ORDER.getCode(), WorkOrderEnum.LINK_CUSTOMER.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(workOrderInApproval)){
            // 副客户有销售机会在审批中,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), name, XbbRefTypeEnum.WORK_ORDER.getName()));
        }
    }

    /**
     * 副客户是否有合同生成
     * @param delId
     * @param corpid
     * @throws XbbException
     */
    private void linkCustomerContact(Long delId, String corpid, JSONObject delData) throws XbbException {
        BoolQueryBuilder booleanQuery = boolQuery();
        String customerAttr = ContractEnum.LINK_CUSTOMER.getAttr();
        String customerContactAttr = ContactEnum.CUSTOMER_NAME.getAttr();
        String linkCustomer = StringConstant.JSON_DATA +StringConstant.POINT + customerAttr;
        booleanQuery.filter(termsQuery(linkCustomer, Arrays.asList(delId)));
        booleanQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        booleanQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        List<String> fieldList = new ArrayList<>();
        fieldList.add(linkCustomer);
        List<PaasFormDataEntityExt> contractList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTRACT, booleanQuery, PaasFormDataEntityExt.class, fieldList);
        if (CollectionsUtil.isNotEmpty(contractList)) {
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120010, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120010.getMsg(), delData.getString(CustomerManagementEnum.NAME.getAttr()) ,XbbRefTypeEnum.CONTRACT.getName() ));
        }
        // 审批中有关联的客户合同
        List<PaasProcessDataEntity> inApprovalDataByIdCondition = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.CONTRACT.getCode(), ContractEnum.LINK_CUSTOMER.getAttr(), Arrays.asList(delId), corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        if (CollectionsUtil.isNotEmpty(inApprovalDataByIdCondition)){
            // 副客户下有关联合同订单,无法删除
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120009, String.format(SystemLabelErrorCodeEnum.API_ERROR_1120009.getMsg(), delData.get(CustomerManagementEnum.NAME.getAttr()), XbbRefTypeEnum.CONTACT.getName()));
        }
    }

    /**
     * 校验上级客户
     *
     * @param data
     * @param corpid
     * @param dataId
     * @throws
     * @author long.rao
     * @date 2020-06-10 19:03
     */
    private void verifyParentCustomer(JSONObject data, String corpid, Long dataId) throws XbbException {
        Long parentId = FastJsonHelper.getLongOrDefaultFromFormData(data, CustomerManagementEnum.PARENT.getAttr(), 0L);
        if (parentId <= 0) {
            return;
        }
        if (dataId != null && dataId > 0) {
            if (Objects.equals(dataId, parentId)) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201022);
            }
            IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.PARENT), dataId));
            boolQueryBuilder.filter(termQuery(FieldTypeEnum.DATAID.getAlias(), parentId));
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, customerIndex.getType()));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(boolQueryBuilder);
            SearchRequest searchRequest = new SearchRequest(customerIndex.getIndex());
            searchRequest.source(sourceBuilder);
            CountRequest countRequest = new CountRequest(searchRequest.indices()[0]);
            countRequest.query(searchRequest.source().query());
            Long count = xbbElasticsearchRestTemplate.count(countRequest);
            if (count !=null && count > 0L) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201023);
            }
        }
    }

    /**
     * 快速编辑之后，触发评分的更新
     * @param corpid
     * @param updateList
     * @param customerUpdateBatchDTO
     */
    private void updateScore4BatchUpdate(String corpid , List<UpdateDataEntity> updateList,CustomerUpdateBatchDTO customerUpdateBatchDTO){
        try{
            if(StringUtil.isNotEmpty(corpid) && CollectionsUtil.isNotEmpty(updateList) && Objects.nonNull(customerUpdateBatchDTO)){
                //列表快速编辑时的formId，attr是编辑的字段。这两个值是在列表快速编辑或者批量编辑单个字段时塞进去的，其他场景可能是空的
                Long formId = customerUpdateBatchDTO.getFormId();
                List<String> attrList = customerUpdateBatchDTO.getAttrList();
                List<Long> updateIdList = updateList.stream().map(item -> item.getId()).collect(Collectors.toList());
                if (Objects.nonNull(formId) && !attrList.isEmpty()) {
                    //formId不为空，表示是列表页快速编辑过来的。需要判断一下编辑的字段是否命中评分规则，如果没有命中规则则不需要去更新评分
                    if (scoreCalculateHelp.isTriggerScoreForQuickEdit(attrList, corpid, formId)) {
                        //评分更新（客户列表页快速编辑）
                        scoreCalculateService.asyncUpdateBatchDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,updateIdList);
                    }
                }else {
                    //评分更新（其他场景的批量编辑）
                    scoreCalculateService.asyncUpdateBatchDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,updateIdList);
                }
            }
        }catch (Exception e){
            LOG.error(" updateScore4BatchUpdate 评分触发更新失败,e-{}-,参数 updateList-{}-",e.getMessage(),JSON.toJSONString(updateList));
        }
    }

    private void updateBatch(CustomerUpdateBatchDTO customerUpdateBatchDTO) throws XbbException {
        try {
            String corpid = customerUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            List<CustomerUpdateDTO> customerUpdateDTOS = customerUpdateBatchDTO.getCustomerList();
            if (Objects.nonNull(customerUpdateDTOS) && !customerUpdateDTOS.isEmpty()) {
                customerUpdateDTOS.forEach((item)->{
                    updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
            }
            if (!updateList.isEmpty()) {
                customerModel.updateBatch(updateList, corpid);
            }
        } catch (Exception e) {
            LOG.error("CustomerServiceImpl.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void customerCommunicateRemoveByScript(CustomerCommunicateDeleteDTO communicateDeleteDTO) throws XbbException {

        Map<String, Object> paramCustomer = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        paramCustomer.put(StringConstant.DEL, communicateDeleteDTO.getDel());
        if (CollectionsUtil.isNotEmpty(communicateDeleteDTO.getCorpidList())) {
            paramCustomer.put("corpidIn", communicateDeleteDTO.getCorpidList());
        }
        paramCustomer.put("updateTimeStart", communicateDeleteDTO.getUpdateTimeStart());
        paramCustomer.put("updateTimeEnd", communicateDeleteDTO.getUpdateTimeEnd());
        paramCustomer.put(StringConstant.COLUMNS, "id,corpid");
        paramCustomer.put(StringConstant.ORDER_BY, "id asc");
        Long idGt = communicateDeleteDTO.getIdGt();
        if (idGt == null) {
            idGt = 0L;
        }
        Long idLte = communicateDeleteDTO.getIdLte();
//        if (idLte == null) {
//            idLte = customerModel.getMaxId();
//        }
        paramCustomer.put("idLte", idLte);

        boolean flag = true;
        int start = 0;
        int pageNum = 1000;
        paramCustomer.put("start", start);
        paramCustomer.put("pageNum", pageNum);
        while (flag) {

            LOG.info("客户需要处理最大id为：" + (idLte == null ? "数据库id最大值" : idLte) + ", 当前处理客户其实id为：" + (idGt + 1));
            paramCustomer.put("idGte", idGt);
            List<CustomerEntityExt> customerEntityExts = customerModel.findEntitysWithoutSub(paramCustomer);

            if(CollectionsUtil.isNotEmpty(customerEntityExts)) {
                Map<String, List<CustomerEntityExt>> collect = customerEntityExts.stream().collect(Collectors.groupingBy(CustomerEntityExt::getCorpid));
                for (Map.Entry<String, List<CustomerEntityExt>> corpidListEntry : collect.entrySet()) {
                    List<Long> allowDeleteCustomerId = corpidListEntry.getValue().stream().map(CustomerEntityExt::getId).collect(Collectors.toList());
                    String corpid = corpidListEntry.getKey();
                    try {
                        if (CollectionsUtil.isEmpty(allowDeleteCustomerId)) {
                            continue;
                        }
                        BoolQueryBuilder boolQueryBuilder = boolQuery();
                        CustomerCommunicateEnum anEnum = CustomerCommunicateEnum.CUSTOMER_NAME;
                        if (Objects.equals(communicateDeleteDTO.getBusinessType(), XbbRefTypeEnum.CLUE.getCode())) {
                            anEnum = CustomerCommunicateEnum.COMMUNICATE_BUSINESS;
                            boolQueryBuilder.filter(termQuery(CustomerCommunicateEnum.getEsAttr4Keyword(CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE), XbbRefTypeEnum.CLUE.getCode()));
                        }
                        boolQueryBuilder.filter(termsQuery(CustomerCommunicateEnum.getEsAttr4Keyword(anEnum), allowDeleteCustomerId));
                        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                        List<String> fieldList = new ArrayList<>();
                        fieldList.add(StringConstant.DATA_ID);
                        List<PaasFormDataEntityExt> customerCommunicateList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                        if (CollectionsUtil.isNotEmpty(customerCommunicateList)) {
                            int allTotal = customerCommunicateList.size();
                            int pageSize = 1000;
                            int index = allTotal / pageSize + 1;
                            int page = 0;
                            int toIndex = 1000;
                            for (int j = 0; j < index; j++) {
                                if (toIndex > allTotal) {
                                    toIndex = allTotal;
                                }
                                List<PaasFormDataEntityExt> resultList = customerCommunicateList.subList(page, toIndex);
                                if (CollectionsUtil.isNotEmpty(resultList)) {
                                    List<Long> deleteList = new ArrayList<>();
                                    resultList.forEach((item) -> {
                                        deleteList.add(item.getDataId());
                                    });
                                    customerCommunicateModel.deleteBatch(deleteList, corpid);
                                    page = page + pageSize;
                                    toIndex = page + pageSize;
                                }
                            }
                        }
                    } catch (Exception e) {
                        LOG.error("customerServiceImpl.customerCommunicateRemoveByScript 执行出错：", e);
                        LOG.error("客户:" + corpid + ">>刷新的客户起始id为：" + allowDeleteCustomerId.get(0) + ", 终止id为：" + allowDeleteCustomerId.get(allowDeleteCustomerId.size() - 1));
                    }

                }
                idGt = customerEntityExts.get(customerEntityExts.size() - 1).getId();
            }

            if (customerEntityExts.size() < pageNum) {
                flag = false;
            }
        }
    }
}
